Skip to main content
Version: 3.xx.xx


We follow a code of conduct when participating in the community. Please read it before you make any contributions.

  • If you plan to work on an issue, mention so in the issue page before you start working on it.
  • If you plan to work on a new feature, create an issue and discuss it with other community members/maintainers.
  • Ask for help in our community room.

Running in development mode​

node version 16 is required.

This project has multiple packages and uses Lerna to manage packages under packages/.

First, install dependencies:

npm install

From now on, depending on the packages you plan to work on, (they are located under packages/ and examples/ directories - see lerna.json) you will need to bootstrap them and start them in watch mode. Instead of running lerna bootstrap directly, read on to see how refine team handles it.

Refer to lerna docs to learn more about it. β†’

Refer to lerna docs to learn more about lerna bootstrap. β†’

Starting the packages you work in watch mode​

You can either bootstrap all packages or only the packages you plan to work on.

To bootstrap all packages (all packages under /examples and under /packages whose names start with @pankod/refine*), you should run:

npm run bootstrap

To bootstrap the specific packages/examples only (all packages under /packages whose names start with @pankod/refine* and specified packages):

npm run bootstrap -- --scope refine-use-select-example

Refer to lerna docs to learn more about scope flag. β†’

npm run bootstrap command bootstraps all packages whose name start with @pankod/refine* and all packages under /examples. If you add filters with --scope flag, you can avoid bootstrapping all packages under /examples.

At this point, all/required packages are bootstrapped. Now you can start the packages you plan to work on in development mode. If you don't want to start all packages in development mode, you should filter them:

npm run build
npm run start -- --scope @pankod/refine-core --scope @pankod/refine-antd --scope refine-use-select-example

This command starts the example named refine-use-select-example in dev mode. The value of the flag --scope is the name that is defined in it's package.json file. Note that --scope flag should be used for every package that should be filtered. If you should start two packages:

Now all filtered packages are running in watch mode. They should re-compile when you make a change in any of them.

Starting documentation in watch mode​

Our documentation is built with Docusaurus. To start it in development mode, run:

cd documentation
npm install
npm run start

Running tests​

npm run test command runs tests for all packages. If you're working on a package (e.g. /packages/core), you can run tests only for that package:

cd packages/core
npm run test

Or you can do it for a specific file:

npm run test -- /src/hooks/export/index.spec.ts

Also, to run a specific file's tests in watch mode:

npm run test -- --watch /src/hooks/export/index.spec.ts

Get coverage report for that file:

npm run test -- --coverage /src/hooks/export/index.spec.ts

When you run the command that produces coverage report, go to /coverage/lcov-report/index.html file to see coverage results. If you run this command in /packages/core directory, then coverage report will be generated in /packages/core/coverage.

Please make sure you contribute well tested code.

Creating Live Previews in Documentation​

We're using live previews powered with react-live to demonstrate our components and logic with refine running at full functionality. To do this, we're defining refine packages as global variables since react-live doesn't support using import statements. To create a live preview, you should add live property to your code blocks in markdown files.


You can use import statements to show them in the code block but they will be ignored when running the code. Check out Defined Scope section to learn more about the available packages and variables.


You can use the following properties to adjust your live blocks:

hideCodeAdds titlefalse
disableScrollDisables the scroll in the previewfalse
previewHeightHeight of the preview400px
urlURL to be shown in the header of the previewhttp://localhost:3000

Hiding Boilerplate Code​

There are two ways to hide/show code sections in your live code blocks; either you can wrap your visible code to // visible-block-start and // visible-block-end comments, or you can use // hide-next-line, // hide-start and // hide-end comments. You can use both of them in the same code block.

// visible-block-start and // visible-block-end

This wrapper can be used to show only the desired part of the code in the code block and will not affect the live preview. Copy code button will only copy the code inside this block. This is the recommended way to hide boilerplate/unwanted code.

// hide-next-line and // hide-start and // hide-end

These magic comments will hide the next line or the wrapped code block. You can use these to hide the code that you want to show in the code blocks. These will also not affect the live preview but those lines will be copied with the copy button. Use these to hide the required code pieces for the live preview but are out of scope for the example. Such as while showing how a property of a component works in live preview, you can hide the required but not relevant props.

Rendering the Preview​

To render the live preview you should call the render function with your component. render function is specific to react-live and it will render the preview in the browser; therefore not needed to be visible in the codeblock, it's recommended to leave the render part outside of the // visible-block wrapper.

Example Usage

```tsx live hideCode url=http://localhost:3000/posts/create
// This is the part we're using the packages from the scope instead of import statements.
const {
} = RefineAntd;

interface ICategory {
id: number;
title: string;

interface IPost {
id: number;
title: string;
content: string;
status: "published" | "draft" | "rejected";
category: { id: number };

// visible-block-start
// Import statements will be ignored in the runtime.
import {
} from "@pankod/refine-antd";

const PostCreate: React.FC = () => {
const { formProps, saveButtonProps } = useForm<IPost>();

const { selectProps: categorySelectProps } = useSelect<ICategory>({
resource: "categories",

const [selectedTab, setSelectedTab] =
useState<"write" | "preview">("write");

return (
<Create saveButtonProps={saveButtonProps}>
<Form {...formProps} layout="vertical">
required: true,
<Input />
name={["category", "id"]}
required: true,
<Select {...categorySelectProps} />
required: true,
label: "Published",
value: "published",
label: "Draft",
value: "draft",
label: "Rejected",
value: "rejected",

// visible-block-end

// This part is required to render the preview.
name: "posts",
list: () => (
<p>This page is empty.</p>
<CreateButton />
create: PostCreate,


Defined Scope​

ReactReact 17
RefineHeadlessDemoPredefined <Refine/> component with simple-rest and react-router-v6 props for easier use
RefineMuiDemoPredefined <Refine/> component with Material UI, simple-rest and react-router-v6 props for easier use
RefineAntdDemoPredefined <Refine/> component with Ant Design, simple-rest and react-router-v6 props for easier use
RefineDemoReactRouterV6Predefined routerProvider generator function with react-router-v6 with MemoryRouter and initialRoutes parameter

Demo components are recommended to be used whenever possible to avoid unnecessary configuration at every code block. They are equipped with the refine-react-router-v6 setup with MemoryRouter, refine-simple-rest data provider and the preferred UI Integration.


Refine component from RefineCore has the default prop reactQueryDevtoolConfig set to false to disable the React Query Dev Tools since it doesn't work with the production version of the React.


RefineDemoReactRouterV6 is a function to create a routerProvider with @pankod/refine-react-router-v6 using MemoryRouter. This function takes one argument initialRoutes which is an array of routes to be rendered initially. For example, if your component is rendered at /posts/create, you can pass ["/posts/create"] as the argument.