> ## Documentation Index
> Fetch the complete documentation index at: https://docs.subframe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Why Subframe

> Subframe is an AI design tool that outputs production-ready React code.

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.

<Info>
  This is the developer documentation. To learn how to use Subframe as a design tool, see the [product guide](/learn).
</Info>

## 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](/concepts/syncing-components).

* **Headless** — Subframe uses [Radix ↗](https://www.radix-ui.com/) 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, Codex, Copilot. You can even connect these tools to Subframe's [MCP server](/guides/mcp-server) to grant direct access to your designs.

## Workflow example

Suppose your designer designs a sign in page in Subframe:

<Frame>
  <img src="https://mintcdn.com/subframe-59800133/PZAsL35sSNLNRpRU/images/developers/signin-page-example.png?fit=max&auto=format&n=PZAsL35sSNLNRpRU&q=85&s=de12630bee565d9ffa9a49621526f9d3" alt="Login page designed in Subframe" width="1964" height="1412" data-path="images/developers/signin-page-example.png" />
</Frame>

Subframe turns the designs into pixel-perfect React code determinstically. The generated code uses your design system components, with stubs for business logic:

<CodeGroup>
  ```tsx SignInPage.tsx expandable theme={null}
  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>) => {
                // [!code highlight:1]
                // TODO: Implement Google sign in
              }}
            />
            <SocialSignInButton
              variant="apple"
              onClick={(event: React.MouseEvent<HTMLButtonElement>) => {
                // [!code highlight:1]
                // 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>) => {
              // [!code highlight:1]
              // TODO: Implement email sign in
            }}
          >
            Continue with email
          </Button>
        </div>
      </div>
    )
  }

  export default SignInPage
  ```

  ```tsx Button.tsx expandable theme={null}
  import React from "react"
  import * as SubframeCore from "@subframe/core"
  import * as SubframeUtils from "../utils"

  interface ButtonRootProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
    disabled?: boolean
    variant?: "brand-primary" | "brand-secondary" | "destructive-primary"
    size?: "large" | "medium" | "small"
    children?: React.ReactNode
    icon?: SubframeCore.IconName
    iconRight?: SubframeCore.IconName
    onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void
    className?: string
  }

  const ButtonRoot = React.forwardRef<HTMLButtonElement, ButtonRootProps>(function ButtonRoot(
    {
      disabled = false,
      variant = "brand-primary",
      size = "medium",
      children,
      icon = null,
      iconRight = null,
      className,
      type = "button",
      ...otherProps
    }: ButtonRootProps,
    ref,
  ) {
    return (
      <button
        className={SubframeUtils.twClassNames(
          "group/3b777358 flex h-8 cursor-pointer items-center justify-center gap-2 rounded-md border-none bg-brand-600 px-3 text-left hover:bg-brand-500 active:bg-brand-600 disabled:cursor-default disabled:bg-neutral-200 hover:disabled:cursor-default hover:disabled:bg-neutral-200 active:disabled:cursor-default active:disabled:bg-neutral-200",
          {
            "h-6 w-auto flex-row flex-nowrap gap-1 px-2 py-0": size === "small",
            "h-10 w-auto px-4 py-0": size === "large",
            "bg-error-600 hover:bg-error-500 active:bg-error-600": variant === "destructive-primary",
            "bg-brand-50 hover:bg-brand-100 active:bg-brand-50": variant === "brand-secondary",
          },
          className,
        )}
        ref={ref}
        type={type}
        disabled={disabled}
        {...otherProps}
      >
        <SubframeCore.Icon
          className={SubframeUtils.twClassNames(
            "text-body font-body text-white group-disabled/3b777358:text-neutral-400",
            {
              "text-heading-3 font-heading-3": size === "large",
              "text-brand-700": variant === "brand-secondary",
            },
          )}
          name={icon}
        />
        <div
          className={SubframeUtils.twClassNames("hidden h-4 w-4 flex-none items-center justify-center gap-2", {
            "h-3 w-3 flex-none": size === "small",
          })}
        >
          <SubframeCore.Loader
            className={SubframeUtils.twClassNames(
              "font-['Inter'] text-[12px] font-[400] leading-[20px] text-white group-disabled/3b777358:text-neutral-400",
              {
                "text-caption font-caption": size === "small",
                "text-brand-700": variant === "brand-secondary",
              },
            )}
          />
        </div>
        {children ? (
          <span
            className={SubframeUtils.twClassNames(
              "whitespace-nowrap text-body-bold font-body-bold text-white group-disabled/3b777358:text-neutral-400",
              {
                "text-caption-bold font-caption-bold": size === "small",
                "text-brand-700": variant === "brand-secondary",
              },
            )}
          >
            {children}
          </span>
        ) : null}
        <SubframeCore.Icon
          className={SubframeUtils.twClassNames(
            "text-body font-body text-white group-disabled/3b777358:text-neutral-400",
            {
              "text-heading-3 font-heading-3": size === "large",
              "text-brand-700": variant === "brand-secondary",
            },
          )}
          name={iconRight}
        />
      </button>
    )
  })

  export const Button = ButtonRoot
  ```

  ```tsx SocialSignInButton.tsx expandable theme={null}
  import React from "react"
  import * as SubframeUtils from "../utils"

  interface SocialSignInButtonRootProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
    disabled?: boolean
    variant?: "facebook" | "google" | "apple"
    onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void
    className?: string
  }

  const SocialSignInButtonRoot = React.forwardRef<HTMLButtonElement, SocialSignInButtonRootProps>(
    function SocialSignInButtonRoot(
      { disabled = false, variant = "facebook", className, type = "button", ...otherProps }: SocialSignInButtonRootProps,
      ref,
    ) {
      return (
        <button
          className={SubframeUtils.twClassNames(
            "group/f1948f75 flex h-10 w-full cursor-pointer items-center justify-center gap-2 rounded-md border border-solid border-neutral-border bg-white px-4 text-left hover:bg-neutral-50 active:bg-white disabled:cursor-default disabled:bg-white hover:disabled:cursor-default hover:disabled:bg-white active:disabled:cursor-default active:disabled:bg-white",
            className,
          )}
          ref={ref}
          type={type}
          disabled={disabled}
          {...otherProps}
        >
          <img
            className="h-5 w-5 flex-none object-cover"
            src={
              variant === "apple"
                ? "https://res.cloudinary.com/subframe/image/upload/v1711417561/shared/kplo8lv2zjit3brqmadv.png"
                : variant === "google"
                ? "https://res.cloudinary.com/subframe/image/upload/v1711417516/shared/z0i3zyjjqkobzuaecgno.svg"
                : "https://res.cloudinary.com/subframe/image/upload/v1711417550/shared/epocfym1zba2deri6krm.png"
            }
          />
          <span className="text-body-bold font-body-bold text-neutral-700 group-disabled/f1948f75:text-neutral-400">
            {variant === "apple"
              ? "Sign in with Apple"
              : variant === "google"
              ? "Sign in with Google"
              : "Sign in with Facebook"}
          </span>
        </button>
      )
    },
  )

  export const SocialSignInButton = SocialSignInButtonRoot
  ```
</CodeGroup>

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 Claude Code, Cursor, or Codex connected to our MCP server:

```tsx SignInPage.tsx expandable theme={null}
import React from "react"
import { Button } from "@/ui/components/Button"
import { SocialSignInButton } from "@/ui/components/SocialSignInButton"
// [!code ++:2]
import { useNavigate } from "react-router-dom"
import { signInWithGoogle, signInWithApple } from "@/lib/auth"

function SignInPage() {
  // [!code ++:1]
  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"
            // [!code ++:4]
            onClick={async () => {
              await signInWithGoogle()
              navigate("/dashboard")
            }}
          />
          <SocialSignInButton
            variant="apple"
            // [!code ++:4]
            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"
          // [!code ++:3]
          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.
