Skip to content

marmelab/shadcn-admin-kit

Repository files navigation

Shadcn Admin Kit

Screenshot

A component kit to build your Admin app with shadcn/ui.

Online Demo

Features

  • CRUD: working List, Show, Edit and Create pages
  • Data Table with sorting, filtering, export, bulk actions, and pagination
  • Form components with data binding and validation
  • View and edit references (one-to-many, many-to-one)
  • Sidebar menu
  • Login page (compatible with any authentication backend)
  • Dashboard page
  • Automatically guess the code based on the data, using Guessers
  • i18n support
  • Light/dark mode
  • Responsive
  • Accessible
  • Compatible with any API (REST, GraphQL, etc.)

Tech Stack

Installation

  1. Create a Vite single-page app

    npm create vite@latest my-shadcn-admin-app -- --template react-ts
  2. Install shadcn/ui in your project.

  3. Download the shadcn-admin-kit components and add them to your project using the shadcn CLI.

    npx shadcn@latest add https://marmelab.com/shadcn-admin-kit/r/shadcn-admin-kit-base.json

    If you use another package manager than npm, use the appropriate command:

    # pnpm
    pnpm dlx shadcn@latest add https://marmelab.com/shadcn-admin-kit/r/shadcn-admin-kit-base.json
    # yarn
    yarn dlx shadcn@latest add https://marmelab.com/shadcn-admin-kit/r/shadcn-admin-kit-base.json
    # bun
    bunx --bun shadcn@latest add https://marmelab.com/shadcn-admin-kit/r/shadcn-admin-kit-base.json
  4. Set the verbatimModuleSyntax option to false in your tsconfig.app.json file to avoid an issue with the latest version of TypeScript.

    {
      "compilerOptions": {
        // ...
        "verbatimModuleSyntax": false
      }
    }

Usage

Use <Admin> As Root Component

The entry point of your application is the <Admin> component. It allows to configure the application adapters, routes, and UI.

You'll need to specify a Data Provider to let the Admin know how to fetch data from your API. A Data Provider is an abstraction that allows you to connect your Admin to any API, whether it's REST, GraphQL, or any other protocol. You can choose from any of the 50+ Data Providers, and you can even build your own.

The following example uses a simple REST adapter called ra-data-simple-rest:

import { Admin } from "@/components/admin/admin";
import simpleRestProvider from 'ra-data-simple-rest';

const dataProvider = simpleRestProvider('http://path.to.my.api');

export const App = () => (
  <Admin dataProvider={dataProvider}>
    {/* Resources go here */}
  </Admin>
);

export default App;

Declare Resources

Then, you'll need to declare the routes of the application. shadcn-admin-kit allows to define CRUD routes (list, edit, create, show), and custom routes. Use the <Resource> component from ra-core (which was automatically added to your dependencies) to define CRUD routes.

For each resource, you can specify a name (which will map to the API endpoint) and the list, edit, create and show components to use.

If you don't know where to start, you can use the built-in guessers to configure the admin for you! The guessers will automatically generate code based on the data returned by your API.

import { Resource } from "ra-core";
import simpleRestProvider from 'ra-data-simple-rest';
import { Admin } from "@/components/admin/admin";
import { ListGuesser } from "@/components/admin/list-guesser";
import { ShowGuesser } from "@/components/admin/show-guesser";
import { EditGuesser } from "@/components/admin/edit-guesser";

const dataProvider = simpleRestProvider('http://path.to.my.api');

export const App = () => (
  <Admin dataProvider={dataProvider}>
    <Resource
      name="posts"
      list={ListGuesser}
      edit={EditGuesser}
      show={ShowGuesser}
    />
  </Admin>
);

The guessers will print out the guessed component code in the console. You can then copy and paste it into your code to create the components to use as list, edit and show view.

// Example output
Guessed List:

import { DataTable } from "@/components/DataTable";
import { List } from "@/components/List";

export const CategoryList = () => (
    <List>
        <DataTable>
            <DataTable.Col source="id" />
            <DataTable.Col source="name" />
        </DataTable>
    </List>
);

Advanced usage

Adding Authentication

You can configure authentication in your Admin by using the authProvider prop. There are many authProviders you can choose from, and you can also build your own.

Once your authProvider is set up, you can pass it to the authProvider prop, and the <Admin> component will automatically display the login page when the user is not authenticated.

import { Resource } from "ra-core";
import simpleRestProvider from 'ra-data-simple-rest';
import { Admin } from "@/components/admin/admin";
import { ListGuesser } from "@/components/admin/list-guesser";
import { authProvider } from './authProvider';

export const App = () => (
  <Admin
    dataProvider={simpleRestProvider('http://path.to.my.api')}
    authProvider={authProvider}
  >
    <Resource
      name="posts"
      list={ListGuesser}
    />
  </Admin>
);

Adding a Dashboard

You can add a dashboard to your Admin by using the dashboard prop. The dashboard can be any React component.

import { Resource } from "ra-core";
import simpleRestProvider from 'ra-data-simple-rest';
import { Admin } from "@/components/admin/admin";
import { ListGuesser } from "@/components/admin/list-guesser";

const Dashboard = () => (
  <div>
    <h1>My Dashboard</h1>
  </div>
);

export const App = () => (
  <Admin
    dataProvider={simpleRestProvider('http://path.to.my.api')}
    dashboard={Dashboard}
  >
    <Resource
      name="posts"
      list={ListGuesser}
    />
  </Admin>
);

Filtering the list

You can filter the list of records by using the filters prop on the <List> component. The filters prop needs to be an array of input components.

import { AutocompleteInput } from "@/components/admin/autocomplete-input";
import { List } from "@/components/admin/list";
import { ReferenceInput } from "@/components/admin/reference-input";
import { TextInput } from "@/components/admin/text-input";

const filters = [
  <TextInput source="q" placeholder="Search products..." label={false} />,
  <ReferenceInput
    source="category_id"
    reference="categories"
    sort={{ field: "name", order: "ASC" }}
  >
    <AutocompleteInput placeholder="Filter by category" label={false} />
  </ReferenceInput>,
];

export const ProductList = () => {
  return (
    <List filters={filters}>
      ...
    </List>
  );
};

Adding Custom Routes

To register your own routes, pass one or several <CustomRoutes> elements as children of <Admin>. Declare as many react-router-dom <Route> as you want inside them.

// in src/App.tsx
import { Resource, CustomRoutes } from 'ra-core';
import { Route } from "react-router-dom";
import { Admin } from "@/components/admin/admin";

import { dataProvider } from './dataProvider';
import posts from './posts';
import comments from './comments';
import { Settings } from './Settings';
import { Profile } from './Profile';

export const App = () => (
    <Admin dataProvider={dataProvider}>
        <Resource name="posts" {...posts} />
        <Resource name="comments" {...comments} />
        <CustomRoutes>
            <Route path="/settings" element={<Settings />} />
            <Route path="/profile" element={<Profile />} />
        </CustomRoutes>
    </Admin>
);

Now, when a user browses to /settings or /profile, the components you defined will appear in the main part of the screen.

Tip: Custom routes don’t automatically appear in the menu. You'll need to customize the <AppSidebar> component if you want custom routes to be accessible from the menu.

Local Development

This project requires Node.js and pnpm.

To install the dependencies, run:

make install

To serve the demo locally, run:

make run

To build the project, run:

make build

To test the UI registry, run:

make test-registry

License

This project is licensed under the MIT License.

About

Component kit to build your Admin app with shadcn/ui

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages