Skip to Content
QuickstartNext.jsNext.js

Next.js Quickstart

Create a new Flexkit Studio in a Next.js application and run it locally.

Create a new Next.js project

Terminal
pnpm create next-app@latest my-flexkit-app --yes
cd my-flexkit-app

Install Flexkit Studio packages

Terminal
pnpm add @flexkit/studio @flexkit/desk @flexkit/asset-manager @flexkit/explorer

Create the Flexkit configuration

Create a flexkit.config.tsx file in the root of your project. This file defines your content schema and Studio configuration.

React
flexkit.config.tsx
import { defineConfig, defineEntity } from '@flexkit/studio';
import { Desk } from '@flexkit/desk';
import { Package, FolderTree } from 'lucide-react';
 
const products = defineEntity({
  name: 'product',
  plural: 'products',
  menu: {
    label: 'Products',
    group: 'catalog',
    icon: <Package />,
  },
  attributes: [
    {
      name: 'name',
      label: 'Product Name',
      scope: 'global',
      dataType: 'string',
      inputType: 'text',
      previewType: 'text',
      isPrimary: true,
      isSearchable: true,
      validation: (z) => z.string().min(1, { message: 'Name is required' }),
      defaultValue: '',
      options: {
        size: 260,
        comment: 'The name of the product',
      },
    },
    {
      name: 'sku',
      label: 'SKU',
      scope: 'global',
      dataType: 'string',
      inputType: 'text',
      isUnique: true,
      isSearchable: true,
      validation: (z) => z.string().min(1, { message: 'SKU is required' }),
      defaultValue: '',
      options: {
        size: 130,
        comment: 'Unique product identifier',
      },
    },
    {
      name: 'description',
      label: 'Description',
      scope: 'global',
      dataType: 'string',
      inputType: 'editor',
      defaultValue: '',
      options: {
        size: 260,
        comment: 'Full product description',
      },
    },
    {
      name: 'price',
      label: 'Price',
      scope: 'global',
      dataType: 'float',
      inputType: 'number',
      previewType: 'text',
      validation: (z) => z.number().min(0, { message: 'Price must be positive' }),
      defaultValue: '',
      options: {
        size: 130,
        comment: 'Product price',
      },
    },
    {
      name: 'category',
      label: 'Category',
      scope: 'relationship',
      dataType: 'string',
      inputType: 'relationship',
      isSearchable: true,
      defaultValue: '',
      relationship: {
        mode: 'single',
        field: 'name',
        entity: 'category',
      },
      options: {
        size: 200,
        comment: 'Product category',
      },
    },
  ],
});
 
const categories = defineEntity({
  name: 'category',
  plural: 'categories',
  menu: {
    label: 'Categories',
    group: 'catalog',
    icon: <FolderTree />,
  },
  attributes: [
    {
      name: 'name',
      label: 'Category Name',
      scope: 'global',
      dataType: 'string',
      inputType: 'text',
      previewType: 'text',
      isPrimary: true,
      isUnique: true,
      isSearchable: true,
      validation: (z) => z.string().min(1, { message: 'Name is required' }),
      defaultValue: '',
      options: {
        size: 200,
        comment: 'The name of the category',
      },
    },
    {
      name: 'slug',
      label: 'URL Slug',
      scope: 'global',
      dataType: 'string',
      inputType: 'text',
      isUnique: true,
      validation: (z) => z.string().min(1, { message: 'Slug is required' }),
      defaultValue: '',
      options: {
        size: 200,
        comment: 'URL-friendly identifier',
      },
    },
    {
      name: 'description',
      label: 'Description',
      scope: 'global',
      dataType: 'string',
      inputType: 'textarea',
      defaultValue: '',
      options: {
        size: 260,
        comment: 'Category description',
      },
    },
  ],
});
 
// Export the Flexkit configuration
export default defineConfig([
  {
    title: 'My Studio',
    projectId: 'your-project-id', // Replace with your unique project ID
    basePath: '/studio',
    menuGroups: [
      {
        title: 'Catalog',
        name: 'catalog',
      },
    ],
    plugins: [
      Desk(),
      // Add more plugins here as needed
    ],
    schema: [products, categories],
  },
]);

Important: Replace 'your-project-id' with the unique project ID of your Flexkit project.

Create the API route handler and Studio page

Create a new API route handler to serve the Flexkit API and a Studio page to render the Flexkit Studio interface. Create the following file structure:

          • route.ts
        • page.tsx
React
app/api/flexkit/[...path]/route.ts
import { createFlexkitApiHandler } from '@flexkit/studio/nextjs';
import { NextResponse } from 'next/server';
import { cookies, headers } from 'next/headers';
 
const flexkitHandler = createFlexkitApiHandler({
  NextResponse,
  cookies,
  headers,
});
 
export const runtime = 'edge';
 
export const { GET, POST, PUT, PATCH, DELETE } = flexkitHandler;

React
app/studio/[[...index]]/page.tsx
 
import { JSX } from 'react';
import '@flexkit/studio/styles.css';
import { FlexkitStudio } from '@flexkit/studio';
import config from '../../../flexkit.config';
 
export default function Page(): JSX.Element | null {
  return <FlexkitStudio config={config} />;
}

Deploy your data schema

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

Run Your Project

Start the development server:

Terminal
pnpm dev

Open your browser and navigate to https://localhost:3000/studio

Last updated on

© 2026