> ## Documentation Index
> Fetch the complete documentation index at: https://subframe-59800133-apg-edit-updates.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Monorepo

> Set up Subframe in a monorepo to share components across multiple apps.

When building complex apps with multiple frontends, it can be useful to use a monorepo setup so you can import the same components into many different apps.

<Note>
  For this guide we'll assume that you're using [Turborepo](https://turbo.build/repo/docs) as your monorepo and
  [Next.js](https://nextjs.org/) for your frontend. Monorepo-specific functionality should work with any package manager
  or framework that supports [workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces?v=true). For more
  information visit the [manual installation guide](/frameworks/manual) and the framework guide for your frontend of
  choice.
</Note>

### Create a package for Subframe

Since we're using Turborepo, we can use the `turbo generate` command to create a package in our monorepo where we'll be importing our Subframe components. We'll call the package `@repo/subframe`.

<Tip>
  If you're using a different monorepo framework or just plain workspaces, you can just duplicate an existing package
  directory and change the contents accordingly.
</Tip>

<CodeGroup>
  ```bash npm theme={null}
  npx turbo generate workspace --name @repo/subframe --type package
  ```

  ```bash yarn theme={null}
  yarn turbo generate workspace --name @repo/subframe --type package
  ```

  ```bash pnpm theme={null}
  pnpm turbo generate workspace --name @repo/subframe --type package
  ```

  ```bash bun theme={null}
  bunx turbo generate workspace --name @repo/subframe --type package
  ```
</CodeGroup>

On the interactive prompt, make sure to select your monorepo's TypeScript and ESLint config packages as `devDependencies` for the next step.

We'll also want to integrate our monorepo's TypeScript and ESLint configuration, so we'll create the following two files:

<CodeGroup>
  ```javascript packages/subframe/eslint.config.mjs theme={null}
  import { config } from "@repo/eslint-config/react-internal"

  /** @type {import("eslint").Linter.Config} */
  export default config
  ```

  ```json packages/subframe/tsconfig.json theme={null}
  {
    "extends": "@repo/typescript-config/react-library.json",
    "compilerOptions": {
      "outDir": "dist"
    },
    "include": ["ui"],
    "exclude": ["node_modules", "dist"]
  }
  ```
</CodeGroup>

### Install Subframe

We now want to install and configure Subframe in our new package. Let's do so by running the `@subframe/cli@latest init` command.

<CodeGroup>
  ```bash npm theme={null}
  cd packages/subframe && npx @subframe/cli@latest init --sync --dir ui
  ```

  ```bash yarn theme={null}
  cd packages/subframe && yarn dlx @subframe/cli@latest init --sync --dir ui
  ```

  ```bash pnpm theme={null}
  cd packages/subframe && pnpx @subframe/cli@latest init --sync --dir ui
  ```

  ```bash bun theme={null}
  cd packages/subframe && bunx --bun @subframe/cli@latest init --sync --dir ui
  ```
</CodeGroup>

<Warning>
  Make sure that you set the import alias to `@repo/subframe/*` during the initialization process. This will make sure that the code imports from Subframe will work within our UI apps later.
  If you forgot to set it, simply edit the importAlias key in your `.subframe/sync.json` file and run `@subframe/cli@latest init` again to sync the changed import alias to your Subframe project.

  ```json packages/subframe/.subframe/sync.json {3} theme={null}
  {
    "directory": "ui",
    "importAlias": "@repo/subframe/*"
  }
  ```
</Warning>

### Export Subframe components from your package

To be able to import our components from this package in other apps in the monorepo, we'll have to make sure they can find the components within our package, as well as Subframe's TailwindCSS config.
We can easily achieve this by setting the `exports` field in our `package.json` accordingly:

```json packages/subframe/package.json {5-10} theme={null}
{
  "name": "@repo/subframe",
  "version": "0.0.0",
  "private": true,
  "exports": {
    ".": "./ui/index.ts",
    "./components/*": "./ui/components/*/index.tsx",
    "./layouts/*": "./ui/layouts/*/index.tsx",
    "./tailwind-config": "./ui/tailwind.config.js"
  },
  "dependencies": {
    "@subframe/core": "^1.141.0"
  },
  "devDependencies": {
    "@repo/eslint-config": "*",
    "@repo/typescript-config": "*"
  }
}
```

<Note>
  Components and page layouts sync as directories (e.g. `components/Button/`), so each subpath export points at the directory's `index.tsx` wrapper rather than a flat `.tsx` file. Subpath patterns are literal — they don't resolve a directory to its `index`, so the `/index.tsx` must be explicit. See [Component directories](/upgrading/component-directories).
</Note>

### Install the `@repo/subframe` package into your app

To install your local package to your app, add the following line to your frontend apps' `dependencies`:

<CodeGroup>
  ```text apps/web/package.json (npm and yarn) theme={null}
  "@repo/subframe": "*"
  ```

  ```text apps/web/package.json (pnpm and bun) theme={null}
  "@repo/subframe": "workspace:*"
  ```
</CodeGroup>

Then run your package manager's `install` command to link your dependencies:

<CodeGroup>
  ```bash npm theme={null}
  npm install
  ```

  ```bash yarn theme={null}
  yarn install
  ```

  ```bash pnpm theme={null}
  pnpm install
  ```

  ```bash bun theme={null}
  bun install
  ```
</CodeGroup>

### Set up TailwindCSS in your frontend app

<Tabs>
  <Tab title="Tailwind v3">
    <Note>
      We assume you've already set up Tailwind CSS for your frontend app. If you haven't done so, follow the [Tailwind
      CSS](https://v3.tailwindcss.com/docs/installation/using-postcss) guide.
    </Note>

    The key change here is that we need to import Subframe's tailwind config `preset` from our local package, as well as include the Subframe component source files in tailwind's `content` array:

    ```javascript apps/web/tailwind.config.js {8, 14} theme={null}
    /** @type {import('tailwindcss').Config} */
    export default {
      content: [
        "./pages/**/*.{js,ts,jsx,tsx}",
        "./components/**/*.{js,ts,jsx,tsx}",
        "./app/**/*.{js,ts,jsx,tsx}",
        "./ui/**/*.{js,ts,jsx,tsx}",
        "../../packages/subframe/ui/**/*.{js,ts,jsx,tsx}",
      ],
      theme: {
        extend: {},
      },
      plugins: [],
      presets: [require("@repo/subframe/tailwind-config")],
    }
    ```
  </Tab>

  <Tab title="Tailwind v4">
    <Note>
      We assume you've already set up Tailwind CSS v4 for your frontend app. If you haven't done so, follow the [Tailwind
      CSS v4](https://tailwindcss.com/docs/installation) guide.
    </Note>

    With Tailwind v4, you need to add two directives to your global CSS file (typically `globals.css`, `index.css`, or `styles.css`):

    ```css apps/web/globals.css {2,3} theme={null}
    @import "tailwindcss";
    @import "../../packages/subframe/ui/theme.css";
    @source "../../packages/subframe/**";
    ```

    * The `@import` directive extends your styles with the Subframe theme
    * The `@source` directive ensures Tailwind discovers the Subframe component files during class name detection

    Make sure to adjust the relative paths based on your monorepo structure.
  </Tab>
</Tabs>

### Use Subframe components in your app

You can now import Subframe components directly into your app. Since we changed the import alias to the name of your local package, all imports generated by the Subframe app will resolve to the components in your `@repo/subframe` package.

<img src="https://mintcdn.com/subframe-59800133-apg-edit-updates/h3QkDAiIDKnbbMvD/images/frameworks/monorepo/subframe-import-example.webp?fit=max&auto=format&n=h3QkDAiIDKnbbMvD&q=85&s=845cbcc212d017c05ee6b78dbf2a7512" alt="@repo/subframe import example" width="805" height="113" data-path="images/frameworks/monorepo/subframe-import-example.webp" />
