Skip to main content
All CollectionsDeveloping with Subframe
Best practices for exporting code
Best practices for exporting code

How to sync your components, add business logic, and fix .

Irvin Zhan avatar
Written by Irvin Zhan
Updated over 4 months ago

In this guide, we will go over the best practices for integrating your Subframe designs into your codebase.

Overview

Subframe uses a copy / paste workflow for exporting code. That means the code for your designs lives in your codebase, and not in a hosted solution like Webflow or Retool.

Here are three tips you should know about this workflow:

1. Components are synced, pages are copy / pasted

Most people use Subframe as the source of truth for their design system. To do this, we recommend using the CLI to sync changes to components to your codebase.

Pages often require refactoring and additional business logic after export. For that reason, pages are never synced via CLI and always copy / pasted.

2. There is no “wrong way” to use Subframe

We find teams often ask if they are doing something wrong. Our answer is if it saves you time – then you are using Subframe correctly.

Another common question is whether everything needs to be Subframe. The answer is no. It’s perfectly ok to have components that aren’t in Subframe yet or you disabled sync for.

3. Use source code as an escape hatch

Subframe is unique in that we give you the source code for everything. The generated code is fully built on open-source libraries like Radix and released on Github as SubframeCore.

Having the source code is important because it avoids vendor lock-in and gives you full flexibility and control in code. If you ever need a feature Subframe doesn’t support yet, you can always create a workaround in code.

Adding business logic

A core principle behind Subframe’s code export flow is that business logic (like making an API call or managing React state) belongs in code, not a design tool. Thus, Subframe does not export any business logic, other than UI-specific interactions like animating an accordion open / close.

Pages

The typical flow for exporting and adding business logic to a page is:

  1. Click on the Code tab on the top-right of the editor to open the code panel.

  2. Copy / paste the CLI command to sync the necessary components

  3. Copy / paste the entire page code

  4. Refactor the code / add your business logic as you see fit

You can find our full guide here

Components

It’s best practice to treat your Subframe components as “dumb” components. You rarely want any application-specific logic in a design system. Instead, business logic will usually be on the page-level.

However you may sometimes want to refactor business logic into a component. Here are two ways you can do that in Subframe.

1. Wrap your “dumb” components (recommended)

We recommend you create a new component that wraps your “dumb” components with business logic. All Subframe components will forward its props to its root React element, meaning you can always add onClick and other handlers as React props. By using this pattern, your components will never be out of sync with Subframe.

For example, you may create a CustomButton like so:

import React from "react";
import { Button } from "@/subframe/components/Button";

interface CustomButtonRootProps extends React.ComponentProps<typeof Button> {
className?: string;
}

export const CustomButton = React.forwardRef<HTMLButtonElement, CustomButtonRootProps>(
function CustomButtonRoot(
{ className, ...otherProps }: CustomButtonRootProps,
ref
) {
/**
* Add any hooks or custom logic here
*/

return (
<Button
className={className}
ref={ref}
onClick={() => {
// You can handle events here too
}}
{...otherProps}
/>
);
}
);

Sometimes your Subframe component has interactive elements like buttons or dynamic content. We recommend you add a slot for those scenarios. Read our full guide on slots and composition here.

2. Disable sync

As a last resort, you can always add your business logic directly to the source code. To prevent the CLI from overwriting your changes, add the following to the top of the file to disable sync:

// @subframe/sync-disable

Any further changes to the component will need to be synced manually.

Did this answer your question?