---
title: TanStack Start
description: Get started with Flexkit Studio in a new TanStack Start project
---

import { Callout } from 'nextra/components';
import { FileTree } from 'nextra/components';
import { Steps } from 'nextra/components';

# TanStack Start Quickstart

Create a new Flexkit Studio in a TanStack Start application and run it locally.



## Before you start

Use Node.js 22 or later and a package manager. [Create a Flexkit project](/docs/getting-started/create-project), copy its Project ID, and ensure your account can deploy its schema. These examples use a project you can safely populate with synthetic data.

Keep the generated application's package versions locked. See [compatibility](/docs/reference/compatibility) when upgrading. Use the directory layout shown here; adjust relative imports if you choose a `src` directory in Next.js.

<Steps>
### Create a new TanStack Start project

**pnpm**

```sh
pnpm create @tanstack/start@latest my-flexkit-app --package-manager pnpm
cd my-flexkit-app
```

**npm**

```sh
npm create @tanstack/start@latest my-flexkit-app -- --package-manager npm
cd my-flexkit-app
```

**yarn**

```sh
yarn create @tanstack/start@latest my-flexkit-app --package-manager yarn
cd my-flexkit-app
```

**bun**

```sh
bun create @tanstack/start@latest my-flexkit-app --package-manager bun
cd my-flexkit-app
```

### Install Flexkit Studio packages

**pnpm**

```sh
pnpm add @flexkit/studio @flexkit/desk @flexkit/asset-manager @flexkit/explorer @flexkit/ai lucide-react
```

**npm**

```sh
npm install @flexkit/studio @flexkit/desk @flexkit/asset-manager @flexkit/explorer @flexkit/ai lucide-react
```

**yarn**

```sh
yarn add @flexkit/studio @flexkit/desk @flexkit/asset-manager @flexkit/explorer @flexkit/ai lucide-react
```

**bun**

```sh
bun add @flexkit/studio @flexkit/desk @flexkit/asset-manager @flexkit/explorer @flexkit/ai lucide-react
```

### Create the Flexkit configuration

Create `flexkit.config.ts` in the project root. This file defines the project schema used by the CLI. The separate Studio configuration below registers browser extensions.

```ts filename="flexkit.config.ts"
import { defineConfig, defineEntity } from '@flexkit/studio';

const categories = defineEntity({
  name: 'category',
  plural: 'categories',
  display: 'name',
  menu: { label: 'Categories' },
  attributes: [
    { name: 'name', label: 'Name', scope: 'local', dataType: 'string', inputType: 'text', searchable: true },
    { name: 'slug', label: 'Slug', scope: 'global', dataType: 'string', inputType: 'text', unique: true },
  ],
});

const products = defineEntity({
  name: 'product',
  plural: 'products',
  display: 'name',
  menu: { label: 'Products' },
  attributes: [
    { name: 'name', label: 'Name', scope: 'local', dataType: 'string', inputType: 'text', searchable: true },
    {
      name: 'sku',
      label: 'SKU',
      scope: 'global',
      dataType: 'string',
      inputType: 'text',
      unique: true,
      searchable: true,
    },
    { name: 'price', label: 'Price', scope: 'local', dataType: 'float', inputType: 'number' },
    { name: 'image', label: 'Image', scope: 'global', dataType: 'asset', inputType: 'asset' },
    { name: 'status', label: 'Status', scope: 'global', dataType: 'string', inputType: 'text', defaultValue: 'draft' },
    {
      name: 'category',
      label: 'Category',
      scope: 'relationship',
      dataType: 'string',
      inputType: 'relationship',
      relationship: { mode: 'single', field: 'name', entity: 'category' },
    },
  ],
});

export default defineConfig({
  title: 'Catalog Studio',
  projectId: 'your-project-id',
  basePath: '/studio',
  scopes: [{ name: 'default', label: 'Default', isDefault: true }],
  schema: [products, categories],
});
```

Keep this configuration free of browser extension imports so the CLI can load it. Create a separate Studio configuration:

```tsx filename="flexkit.studio.tsx"
import { defineConfig } from '@flexkit/studio';
import { Desk } from '@flexkit/desk';
import { AssetManager } from '@flexkit/asset-manager';
import { Explorer } from '@flexkit/explorer';
import { AI } from '@flexkit/ai';
import project from './flexkit.config';

export default defineConfig({
  ...project,
  extensions: [Desk(), AssetManager(), Explorer(), AI()],
});
```

<Callout type="info">**Important**: Replace `'your-project-id'` with your Flexkit project ID.</Callout>

`local` fields use the selected scope in Studio. If the active scope does not have a local value yet, the default scope value is shown instead.

### Create TanStack Start routes for Studio and API

Create the following files:

<FileTree>
  <FileTree.Folder name="src" open>
    <FileTree.Folder name="routes" open>
      <FileTree.File name="index.tsx" />
      <FileTree.File name="studio.tsx" />
      <FileTree.Folder name="studio" open>
        <FileTree.File name="$.tsx" />
      </FileTree.Folder>
      <FileTree.Folder name="api" open>
        <FileTree.Folder name="flexkit" open>
          <FileTree.File name="$.tsx" active />
        </FileTree.Folder>
      </FileTree.Folder>
    </FileTree.Folder>
  </FileTree.Folder>
</FileTree>

```tsx filename="src/routes/index.tsx"
import { createFileRoute, redirect } from '@tanstack/react-router';

export const Route = createFileRoute('/')({
  beforeLoad: () => {
    throw redirect({ to: '/studio' });
  },
});
```

```tsx filename="src/routes/studio.tsx"
import { createFileRoute } from '@tanstack/react-router';
import '@flexkit/studio/styles.css';
import '@flexkit/desk/styles.css';
import '@flexkit/asset-manager/styles.css';
import '@flexkit/explorer/styles.css';
import '@flexkit/ai/styles.css';
import { FlexkitStudio } from '@flexkit/studio';
import config from '../../flexkit.studio';

export const Route = createFileRoute('/studio')({
  ssr: false,
  component: StudioPage,
});

function StudioPage() {
  return <FlexkitStudio config={config} />;
}
```

```tsx filename="src/routes/studio/$.tsx"
import { createFileRoute } from '@tanstack/react-router';
import '@flexkit/studio/styles.css';
import '@flexkit/desk/styles.css';
import '@flexkit/asset-manager/styles.css';
import '@flexkit/explorer/styles.css';
import '@flexkit/ai/styles.css';
import { FlexkitStudio } from '@flexkit/studio';
import config from '../../../flexkit.studio';

export const Route = createFileRoute('/studio/$')({
  ssr: false,
  component: StudioPage,
});

function StudioPage() {
  return <FlexkitStudio config={config} />;
}
```

```tsx filename="src/routes/api/flexkit/$.tsx"
import { createFileRoute } from '@tanstack/react-router';
import { createFlexkitFetchHandler } from '@flexkit/studio/tanstack-start';

const flexkitHandler = createFlexkitFetchHandler();

export const Route = createFileRoute('/api/flexkit/$')({
  component: () => null,
  server: {
    handlers: {
      GET: async ({ request }) => {
        return flexkitHandler(request);
      },
      POST: async ({ request }) => {
        return flexkitHandler(request);
      },
      PUT: async ({ request }) => {
        return flexkitHandler(request);
      },
      PATCH: async ({ request }) => {
        return flexkitHandler(request);
      },
      DELETE: async ({ request }) => {
        return flexkitHandler(request);
      },
    },
  },
});
```

### Deploy your data schema

<Callout>Install the [Flexkit CLI](/docs/cli) to deploy your data schema.</Callout>

```bash
flexkit login
flexkit whoami
flexkit deploy
```

### Run your project

**pnpm**

```sh
pnpm dev
```

**npm**

```sh
npm run dev
```

**yarn**

```sh
yarn dev
```

**bun**

```sh
bun run dev
```

Open your browser and navigate to `http://localhost:3000/studio`.

</Steps>

## Confirm your first success

Sign into Studio with the account that has access to the configured project. Open Desk, create a Category and Product, save, and reopen the record. Open Explorer and run the [tutorial read](/docs/api/graphql/queries). The record ID and global SKU should agree with the saved record.

If the UI loads but data does not, check the project ID, completed schema deployment, role/spaces, and API handler route. Missing styles usually indicate an omitted extension stylesheet. Continue with [your first workflow](/docs/getting-started/first-workflow), then [production deployment](/docs/deployment).


---

[View full sitemap](/docs/sitemap.md)
