Skip to Content
Framework quickstartsTanStackTanstack

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, 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 when upgrading. Use the directory layout shown here; adjust relative imports if you choose a src directory in Next.js.

Create a new TanStack Start project

pnpm

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

npm

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

yarn

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

bun

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

Install Flexkit Studio packages

pnpm

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

npm

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

yarn

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

bun

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.

TypeScript
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:

React
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()],
});
Important: Replace 'your-project-id' with your Flexkit project ID.

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:

      • index.tsx
      • studio.tsx
        • $.tsx
          • $.tsx
React
src/routes/index.tsx
import { createFileRoute, redirect } from '@tanstack/react-router';
 
export const Route = createFileRoute('/')({
  beforeLoad: () => {
    throw redirect({ to: '/studio' });
  },
});
React
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} />;
}
React
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} />;
}
React
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

Install the Flexkit CLI to deploy your data schema.
flexkit login
flexkit whoami
flexkit deploy

Run your project

pnpm

pnpm dev

npm

npm run dev

yarn

yarn dev

bun

bun run dev

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

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. 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, then production deployment.

Last updated on

© 2026