Skip to main content
Designers and developers have always worked in separate tools: designers make mockups, developers translate them to code. But what ships never quite matches what was designed, and developers had wasted hours making it that way. Subframe is a design tool that eliminates the translation step. Designers use the same components you ship to production, so you spend more time building product, not translating designs.
This is the developer documentation. To learn how to use Subframe as a design tool, see the product guide.

Code quality matters

Unlike other AI design tools, Subframe’s code output is deterministic. There’s no LLM misinterpreting your design—what is designed is exactly what you get in clean React code, every time. Our code philosophy:
  • Consistent — All designs are created from the same consistent design system. No more custom, one-off implementations.
  • Open code — Avoid platform lock-in. Code generated by Subframe lives in your codebase, copy/pasted or synced via the CLI.
  • Headless — Subframe uses Radix under the hood, which maintains a cleaner separation of concerns between presentation and behavior.
  • AI-ready — The generated code follows best practices to be modified further by AI tools like Claude Code, Cursor, Copilot. You can even connect these tools to Subframe’s MCP server to grant direct access to your designs.

Workflow example

Suppose your designer designs a sign in page in Subframe:
Login page designed in Subframe
Subframe turns the designs into pixel-perfect React code determinstically. The generated code uses your design system components, with stubs for business logic:
import React from "react"
import { Button } from "@/ui/components/Button"
import { SocialSignInButton } from "@/ui/components/SocialSignInButton"

function SignInPage() {
  return (
    <div className="flex h-full w-full flex-col items-center justify-center bg-white">
      <div className="flex w-64 flex-col items-center justify-center gap-8">
        <div className="flex flex-col items-center justify-center gap-1">
          <img
            className="h-16 flex-none object-cover"
            src="https://res.cloudinary.com/subframe/image/upload/v1767591134/uploads/302/zzfsz5tcwky0pkjkru9d.png"
          />
          <span className="text-heading-2 font-heading-2 text-default-font">Welcome</span>
          <span className="text-body font-body text-subtext-color">Login or sign up below</span>
        </div>
        <div className="flex w-full flex-col items-center gap-2">
          <SocialSignInButton
            variant="google"
            onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
              // TODO: Implement Google sign in
            }}
          />
          <SocialSignInButton
            variant="apple"
            onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
              // TODO: Implement Apple sign in
            }}
          />
        </div>
        <div className="flex h-px w-full flex-none flex-col items-center gap-2 bg-neutral-border" />
        <Button
          className="h-10 w-full flex-none"
          variant="brand-secondary"
          size="large"
          icon="FeatherMail"
          onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
            // TODO: Implement email sign in
          }}
        >
          Continue with email
        </Button>
      </div>
    </div>
  )
}

export default SignInPage
All that’s left is to export it to your codebase and add business logic. You can do that manually or with AI assistants like Cursor or Claude Code connected to our MCP server:
SignInPage.tsx
import React from "react"
import { Button } from "@/ui/components/Button"
import { SocialSignInButton } from "@/ui/components/SocialSignInButton"
import { useNavigate } from "react-router-dom"
import { signInWithGoogle, signInWithApple } from "@/lib/auth"

function SignInPage() {
  const navigate = useNavigate()

  return (
    <div className="flex h-full w-full flex-col items-center justify-center bg-white">
      <div className="flex w-64 flex-col items-center justify-center gap-8">
        <div className="flex flex-col items-center justify-center gap-1">
          <img
            className="h-16 flex-none object-cover"
            src="https://res.cloudinary.com/subframe/image/upload/v1767591134/uploads/302/zzfsz5tcwky0pkjkru9d.png"
          />
          <span className="text-heading-2 font-heading-2 text-default-font">Welcome</span>
          <span className="text-body font-body text-subtext-color">Login or sign up below</span>
        </div>
        <div className="flex w-full flex-col items-center gap-2">
          <SocialSignInButton
            variant="google"
            onClick={async () => {
              await signInWithGoogle()
              navigate("/dashboard")
            }}
          />
          <SocialSignInButton
            variant="apple"
            onClick={async () => {
              await signInWithApple()
              navigate("/dashboard")
            }}
          />
        </div>
        <div className="flex h-px w-full flex-none flex-col items-center gap-2 bg-neutral-border" />
        <Button
          className="h-10 w-full flex-none"
          variant="brand-secondary"
          size="large"
          icon="FeatherMail"
          onClick={() => {
            navigate("/sign-in/email")
          }}
        >
          Continue with email
        </Button>
      </div>
    </div>
  )
}

export default SignInPage
That’s it. You just went from design to production-ready code in minutes, without translating mockups or pixel-pushing. With Subframe, you focus on the real engineering work.