# Shadcn Admin Kit Shadcn Admin Kit is a modern React component library for building admin interfaces with minimal boilerplate. Built on top of shadcn/ui and ra-core (React-Admin core), it provides a comprehensive set of components for creating full-featured CRUD applications with authentication, data tables, forms, and relationship management. The library combines the accessibility and aesthetics of Radix UI with the battle-tested admin framework patterns from React-Admin, all styled with Tailwind CSS. The kit is designed to work with any backend API (REST, GraphQL, or custom protocols) through data provider adapters. It includes intelligent guessers that scaffold code automatically based on your API responses, making it quick to prototype admin interfaces. With full TypeScript support, built-in responsive design, internationalization capabilities, and dark mode support, it accelerates admin application development while maintaining flexibility for customization. ## Admin Component Root application component that configures data provider, authentication, routing, and theming. ```tsx import { Admin, Resource } from "@/components/admin"; import simpleRestProvider from 'ra-data-simple-rest'; import { authProvider } from './authProvider'; import { ProductList, ProductEdit, ProductCreate } from './products'; import { Dashboard } from './dashboard'; const dataProvider = simpleRestProvider('https://api.example.com'); export const App = () => ( record.name} /> ); ``` ## List Component Displays paginated, sortable, and filterable lists of records with create and export actions. ```tsx import { List, DataTable, TextInput, SelectInput, ReferenceInput, AutocompleteInput } from "@/components/admin"; const filters = [ , , ]; export const ProductList = () => ( ); ``` ## Edit Component Provides a form interface for editing existing records with automatic data loading and saving. ```tsx import { Edit, SimpleForm, TextInput, NumberInput, ReferenceInput, AutocompleteInput, BooleanInput } from "@/components/admin"; import { required, minValue, maxValue } from "ra-core"; export const ProductEdit = () => (
); ``` ## Create Component Form interface for creating new records with validation and redirect options. ```tsx import { Create, SimpleForm, TextInput, NumberInput, ReferenceInput, AutocompleteInput } from "@/components/admin"; import { required, minValue } from "ra-core"; export const ProductCreate = () => ( } />
); ``` ## Show Component Displays a single record in read-only mode with customizable field layout. ```tsx import { Show, SimpleShowLayout, TextField, NumberField, ReferenceField, DateField, BooleanField } from "@/components/admin"; export const ProductShow = () => ( ); ``` ## DataTable Component Advanced data table with sorting, column visibility, bulk actions, and row navigation. ```tsx import { List, DataTable, ReferenceField, TextField, NumberField, DateField, BulkDeleteButton, BulkExportButton } from "@/components/admin"; export const OrderList = () => ( } > ( {record.status} )} /> ); ``` ## SimpleForm Component Form wrapper with integrated validation, error handling, and toolbar. ```tsx import { Edit, SimpleForm, TextInput, SaveButton, DeleteButton, Toolbar } from "@/components/admin"; import { required, email } from "ra-core"; const CategoryToolbar = () => ( ); export const CategoryEdit = () => ( } validate={(values) => { const errors = {}; if (values.name && values.name.length < 3) { errors.name = "Name must be at least 3 characters"; } return errors; }} > ); ``` ## TextInput Component Text input field with label, validation, error display, and helper text. ```tsx import { SimpleForm, TextInput } from "@/components/admin"; import { required, minLength, maxLength, regex } from "ra-core"; ``` ## SelectInput Component Dropdown select with choices, supporting static lists and dynamic creation. ```tsx import { SimpleForm, SelectInput, ReferenceInput } from "@/components/admin"; import { required } from "ra-core"; `${user.first_name} ${user.last_name}`} emptyText="No author" emptyValue={null} /> ``` ## AutocompleteInput Component Searchable dropdown ideal for large datasets with remote filtering. ```tsx import { SimpleForm, ReferenceInput, AutocompleteInput } from "@/components/admin"; import { required } from "ra-core"; `${customer.first_name} ${customer.last_name} (${customer.email})`} inputText={(customer) => `${customer.first_name} ${customer.last_name}`} filterToQuery={(searchText) => ({ q: searchText })} validate={required()} /> } onCreate={(tagName) => { const newTag = { name: tagName }; return dataProvider.create('tags', { data: newTag }) .then(({ data }) => data); }} /> ``` ## ReferenceInput Component Input for selecting records from related resources (foreign key relationships). ```tsx import { SimpleForm, ReferenceInput, AutocompleteInput, SelectInput } from "@/components/admin"; import { required } from "ra-core"; `${supplier.name} - ${supplier.city}`} validate={required()} /> } validate={required()} /> ``` ## ReferenceField Component Displays fields from related records by following foreign key relationships. ```tsx import { List, DataTable, ReferenceField, TextField, EmailField, ChipField } from "@/components/admin"; export const OrderList = () => ( (
{referenceRecord?.name}
{referenceRecord?.reference}
)} />
); ``` ## TextField Component Displays text values from record fields with optional formatting. ```tsx import { Show, SimpleShowLayout, TextField } from "@/components/admin"; export const CustomerShow = () => ( (
{record.address}
{record.city}, {record.state} {record.zipcode}
)} />
); ``` ## NumberField Component Displays formatted numbers with currency, percentage, and locale support. ```tsx import { List, DataTable, NumberField } from "@/components/admin"; export const ProductList = () => ( value / 10} /> ); ``` ## BulkActionsToolbar Component Toolbar for performing bulk operations on selected records. ```tsx import { List, DataTable, BulkActionsToolbar, BulkDeleteButton, BulkExportButton, BulkUpdateButton } from "@/components/admin"; import { useListContext, useUpdateMany, useNotify, useUnselectAll } from "ra-core"; const BulkSetFeaturedButton = () => { const { selectedIds } = useListContext(); const notify = useNotify(); const unselectAll = useUnselectAll("products"); const [updateMany, { isPending }] = useUpdateMany( "products", { ids: selectedIds, data: { featured: true } }, { onSuccess: () => { notify("Products updated successfully", { type: "success" }); unselectAll(); } } ); return ( ); }; export const ProductList = () => ( } > ); ``` ## Data Provider Implementation Interface for connecting to any backend API (REST, GraphQL, custom). ```tsx // Simple REST data provider import simpleRestProvider from 'ra-data-simple-rest'; export const dataProvider = simpleRestProvider('https://api.example.com'); // Custom data provider import { DataProvider } from 'ra-core'; export const customDataProvider: DataProvider = { getList: async (resource, params) => { const { page, perPage } = params.pagination; const { field, order } = params.sort; const query = { sort: field, order: order, page: page, per_page: perPage, filter: JSON.stringify(params.filter), }; const response = await fetch( `https://api.example.com/${resource}?${new URLSearchParams(query)}` ); const json = await response.json(); return { data: json.items, total: json.total, }; }, getOne: async (resource, params) => { const response = await fetch(`https://api.example.com/${resource}/${params.id}`); const data = await response.json(); return { data }; }, create: async (resource, params) => { const response = await fetch(`https://api.example.com/${resource}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params.data), }); const data = await response.json(); return { data }; }, update: async (resource, params) => { const response = await fetch(`https://api.example.com/${resource}/${params.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params.data), }); const data = await response.json(); return { data }; }, delete: async (resource, params) => { await fetch(`https://api.example.com/${resource}/${params.id}`, { method: 'DELETE', }); return { data: params.previousData }; }, getMany: async (resource, params) => { const query = { ids: params.ids.join(',') }; const response = await fetch( `https://api.example.com/${resource}?${new URLSearchParams(query)}` ); const data = await response.json(); return { data }; }, getManyReference: async (resource, params) => { const { page, perPage } = params.pagination; const { field, order } = params.sort; const query = { [params.target]: params.id, sort: field, order: order, page: page, per_page: perPage, }; const response = await fetch( `https://api.example.com/${resource}?${new URLSearchParams(query)}` ); const json = await response.json(); return { data: json.items, total: json.total, }; }, updateMany: async (resource, params) => { const responses = await Promise.all( params.ids.map(id => fetch(`https://api.example.com/${resource}/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params.data), }) ) ); return { data: params.ids }; }, deleteMany: async (resource, params) => { await Promise.all( params.ids.map(id => fetch(`https://api.example.com/${resource}/${id}`, { method: 'DELETE', }) ) ); return { data: params.ids }; }, }; ``` ## Auth Provider Implementation Authentication interface supporting login, logout, permissions, and identity management. ```tsx import { AuthProvider, HttpError } from "ra-core"; export const authProvider: AuthProvider = { login: async ({ username, password }) => { const response = await fetch('https://api.example.com/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); if (response.ok) { const { token, user } = await response.json(); localStorage.setItem('token', token); localStorage.setItem('user', JSON.stringify(user)); return Promise.resolve(); } return Promise.reject( new HttpError('Invalid credentials', 401, { message: 'Invalid username or password' }) ); }, logout: async () => { localStorage.removeItem('token'); localStorage.removeItem('user'); return Promise.resolve(); }, checkAuth: async () => { const token = localStorage.getItem('token'); if (!token) { return Promise.reject(); } // Verify token with backend const response = await fetch('https://api.example.com/auth/verify', { headers: { 'Authorization': `Bearer ${token}` } }); return response.ok ? Promise.resolve() : Promise.reject(); }, checkError: async (error) => { const status = error.status; if (status === 401 || status === 403) { localStorage.removeItem('token'); return Promise.reject(); } return Promise.resolve(); }, getIdentity: async () => { const userStr = localStorage.getItem('user'); if (!userStr) { return Promise.reject(); } const user = JSON.parse(userStr); return Promise.resolve({ id: user.id, fullName: `${user.first_name} ${user.last_name}`, avatar: user.avatar_url, }); }, getPermissions: async () => { const userStr = localStorage.getItem('user'); if (!userStr) { return Promise.reject(); } const user = JSON.parse(userStr); return Promise.resolve(user.role); }, }; // Usage in App import { Admin } from "@/components/admin"; import { authProvider } from "./authProvider"; {/* Resources */} ``` --- ## Summary Shadcn Admin Kit provides a complete solution for building production-ready admin interfaces with minimal configuration. The primary use cases include internal business tools, content management systems, e-commerce back-offices, data dashboards, and API administration panels. The library excels at rapid prototyping through its guesser components while remaining flexible enough for complex, customized implementations. It handles common admin requirements out-of-the-box: pagination, sorting, filtering, validation, authentication, authorization, optimistic updates, error handling, and bulk operations. Integration patterns center around three core concepts: data providers for API connectivity (with 50+ pre-built adapters for popular backends), auth providers for security, and resource declarations that map UI components to API endpoints. The component architecture encourages composition, allowing developers to start with high-level components like `` and `` for standard views, then progressively customize with lower-level building blocks. All components integrate seamlessly with React Hook Form for validation, TanStack Query for data fetching, and React Router for navigation, while maintaining full type safety through TypeScript generics that flow from the data layer through to the UI.