npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@devfamily/admiral

v6.0.0

Published

Admiral is a frontend framework for creating back office using React. It provides out-of-the-box components and tools that make developing an admin interface easy and fast.

Readme


Features

  • CRUD generation — define a resource config, get index/create/update pages with tables, forms, filters, and pagination
  • 30+ UI components — Table, Form inputs, Select, DatePicker, Drawer, Tabs, Upload, Notification, and more
  • Conditional & dependent fieldsvisibleWhen / disabledWhen / requiredWhen rules on any input, Form.When groups, cascading selects
  • Validation-aware form tabsForm.Tabs shows per-tab error badges and switches to the first invalid tab on submit
  • File-based routing — pages directory maps to routes automatically (like Next.js)
  • Authentication — login, logout, OAuth (Google, GitHub, Jira), session checks
  • Theming — light/dark modes, fully customizable CSS presets
  • Localization — built-in i18n with swappable locale packs
  • TypeScript — full type coverage across all components and hooks

Tech Stack

React 19 • React Router 7 • Vite 6 • TypeScript 5.7 • @dnd-kit • @floating-ui • rc-* components • date-fns 4

Quick Start

Option 1 — scaffold a new project (recommended)

npx create-admiral-app@latest

You'll be prompted to choose:

  • With Express.js backend — fully configured template with an API server
  • Frontend only — just the admin panel, bring your own API

Then cd into the project, npm install, npm run dev — and you have a working admin panel.

Option 2 — add to an existing app

Requires Node.js >= 20 and a bundler (the examples below use Vite).

1. Install the package and its peer dependencies:

npm install @devfamily/admiral react@^19 react-dom@^19 react-router-dom@^7 axios@^1

2. Create the app entry. Import the styles once, wrap everything in <Admin>:

// src/App.tsx
import { Admin, createRoutesFrom } from '@devfamily/admiral'
import '@devfamily/admiral/style.css'
import Menu from './menu'
import dataProvider from './dataProvider'

// createRoutesFrom takes a map of page modules; with Vite use import.meta.glob
const Routes = createRoutesFrom(import.meta.glob('../pages/**/*', { eager: true }))

export default function App() {
    return (
        <Admin dataProvider={dataProvider('/api')} menu={Menu}>
            <Routes />
        </Admin>
    )
}

3. Add a menu:

// src/menu.tsx
import { Menu, MenuItemLink } from '@devfamily/admiral'

export default function AppMenu() {
    return (
        <Menu>
            <MenuItemLink icon="FiUsers" name="Users" to="/users" />
        </Menu>
    )
}

4. Add a data provider — the object that tells Admiral how to talk to your API. Copy src/dataProvider.ts as a starting point; the contract it implements is described in Data Provider below.

5. Create your first page — see the CRUD example. Done: /users now renders a table with forms, filters, and pagination.

Option 3 — run this repo

git clone https://github.com/dev-family/admiral.git
cd admiral
yarn
yarn dev

Open http://localhost:3000 — you'll see Admiral running on mock data, with the source for every page in pages/ and src/.

Core Concepts

Admiral apps are built from a handful of pieces: an <Admin> root, file-based routing, CRUD pages generated from a config, a data provider (and optionally an auth provider) that connect Admiral to your API, plus forms, filters, themes, and locales. Each piece is described below.

<Admin>

The root component. It wires up routing, theming, data fetching, auth, localization, and notifications — every other Admiral feature expects to live inside it.

<Admin
    dataProvider={dataProvider(apiUrl)} // required: how to fetch data
    menu={Menu} // required: sidebar menu component
    authProvider={authProvider(apiUrl)} // optional: enables the login flow
    themePresets={{ light, dark }} // optional: custom theme
    locale={admiralLocales.ruRU} // optional: translations
    logo={Logo} // optional: sidebar logo
    oauthProviders={[OAuthProvidersEnum.Google]} // optional: OAuth buttons
>
    <Routes />
</Admin>

Routing

Admiral uses file-system based routing. Files in the pages/ directory map to routes:

| File | Route | | ------------------------ | --------------- | | pages/index.tsx | / | | pages/users/index.tsx | /users | | pages/users/create.tsx | /users/create | | pages/users/[id].tsx | /users/:id |

CRUD Pages

Define a resource in one file — Admiral generates the index, create, and update pages:

// pages/users/index.tsx
import { createCRUD, TextInput, SelectInput } from '@devfamily/admiral'

export const { IndexPage, CreatePage, UpdatePage } = createCRUD({
    resource: 'users',
    path: '/users',
    index: {
        title: 'Users',
        newButtonText: 'Create User',
        tableColumns: [
            { title: 'ID', dataIndex: 'id', key: 'id' },
            { title: 'Name', dataIndex: 'name', key: 'name' },
            { title: 'Email', dataIndex: 'email', key: 'email' },
        ],
    },
    form: {
        create: {
            fields: (
                <>
                    <TextInput label="Name" name="name" required />
                    <TextInput label="Email" name="email" required />
                    <SelectInput label="Role" name="role_id" />
                </>
            ),
        },
        edit: {
            fields: (
                <>
                    <TextInput label="Name" name="name" required />
                    <TextInput label="Email" name="email" required />
                    <SelectInput label="Role" name="role_id" />
                </>
            ),
        },
    },
})

export default IndexPage

The full demo configs live in src/crud/.

Data Provider

The DataProvider interface defines how Admiral communicates with your API:

interface DataProvider {
    getList: (resource, params) => Promise<{ items: any[]; meta: PaginationMeta }>
    getOne: (resource, params) => Promise<{ data: any; values?: any }>
    create: (resource, params) => Promise<{ data: any }>
    update: (resource, params) => Promise<{ data: any }>
    deleteOne: (resource, params) => Promise<{ data: any }>
    getCreateFormData: (resource) => Promise<{ data?: any; values?: any }>
    getUpdateFormData: (resource, params) => Promise<{ data: any; values?: any }>
    getFiltersFormData: (resource, urlState?) => Promise<{ values?: any }>
    reorderList: (resource, params) => Promise<void>
}

See src/dataProvider.ts for a full implementation example.

API response format:

// GET /api/users?page=1&page_size=10
{
    "items": [{ "id": 1, "name": "John", "email": "[email protected]" }],
    "meta": { "current_page": 1, "last_page": 5, "per_page": 10, "total": 50 }
}

// Validation errors (HTTP 422)
{
    "errors": { "email": ["Email is required"] },
    "message": "Validation failed"
}

Auth Provider

Pass an authProvider to <Admin> and Admiral renders a login page, guards all routes, and keeps the session checked:

interface AuthProvider {
    login: (params: { username: string; password: string }) => Promise<any>
    logout: (params?: any) => Promise<void | false | string>
    checkAuth: (params?: any) => Promise<void>
    getIdentity: () => Promise<{ email: string; name: string }>
    oauthLogin?: (provider: OAuthProvidersEnum) => Promise<{ redirect: string }>
    oauthCallback?: (provider: OAuthProvidersEnum, data: string) => Promise<any>
}

See src/authProvider.ts for a full implementation example.

Forms & Inputs

CRUD forms are composed from ready-made inputs — each binds to a form value by name:

TextInput, MultilineTextInput, PasswordInput, SlugInput, SelectInput, AjaxSelectInput, RadioInput, BooleanInput, DatePickerInput, DateRangePickerInput, TimePickerInput, ColorPickerInput, EditorInput, FilePictureInput, DraggerInput, ArrayInput, TranslatableInput

Inside any form (or a custom input) the useForm() hook gives access to values, errors, and setters. Standalone forms outside CRUD are available via the Form component from @devfamily/admiral/form.

Conditional & dependent fields. Every input takes visibleWhen / disabledWhen / requiredWhen (a (values) => boolean or a JSON rule), <Form.When> reveals a group by one rule, and AjaxSelectInput supports resetOnChangeOf cascades (e.g. country → city). See Conditional & dependent fields.

Form.Tabs — validation-aware tabs. Long forms split into tabs that stay honest about errors: each tab shows a badge with its invalid-field count, and a failed submit switches to the first tab that needs attention (fields hidden by rules are skipped). See Form.Tabs.

Filters

Add a filter drawer to a CRUD index page with the filter key, and promote any of the fields to always-visible quick filters with quickFilters:

createCRUD({
    // ...
    filter: {
        topToolbarButtonText: 'Filter',
        fields: (
            <>
                <TextInput label="Name" name="name" />
                <BooleanInput label="Active" name="is_active" />
            </>
        ),
        quickFilters: ['name', 'is_active'],
    },
})

Applied filters are reflected in the URL, so filtered views are shareable and bookmarkable. A complete example: src/crud/quickFilters.tsx.

Theming

Light and dark modes work out of the box (with a switcher in the header). To customize colors, pass your own presets to <Admin>:

import themeLight from './theme/presets/themeLight'
import themeDark from './theme/presets/themeDark'
;<Admin themePresets={{ light: themeLight, dark: themeDark }}>
    <Routes />
</Admin>

Presets use @consta/uikit Theme under the hood. See admiral/theme/presets for the preset structure and CSS variables.

Localization

English is the default; a Russian pack ships in the box. Pass a ready-made pack to <Admin>, or a partial object — any top-level section you provide replaces the default one:

import { Admin, admiralLocales } from '@devfamily/admiral'
;<Admin locale={admiralLocales.ruRU}>
    <Routes />
</Admin>

Module Imports

Admiral supports granular imports to reduce bundle size:

import { Admin, createCRUD, createRoutesFrom } from '@devfamily/admiral'
import { Table, Button, Select, Drawer } from '@devfamily/admiral/ui'
import { Form, TextInput, SelectInput } from '@devfamily/admiral/form'
import { useTheme } from '@devfamily/admiral/theme'
import '@devfamily/admiral/style.css'

Hooks

| Hook | Description | | --------------------- | ------------------------------------------------------------------ | | useForm() | Access form values, errors, options, and setters inside CRUD forms | | useTheme() | Get and set the active theme (light / dark) | | useNav() | Control sidebar collapse state and mobile burger menu | | useGetIdentity() | Get the authenticated user's identity | | useLocaleProvider() | Access the current locale configuration | | useUrlState() | Read/write state synced to the URL query string |

Icons

Admiral uses React Icons (v5). Pass any icon name as a string or use JSX components directly.

Examples

Migrating from v5

v6 is a breaking release: React 19, React Router 7, ESM-only package, stricter types. The full checklist lives in MIGRATION.md. Migrating with an AI coding agent? Point it at MIGRATION_AI.md — the same guide as deterministic find → change → verify steps.

Using AI assistants

Two machine-oriented docs ship inside the npm package, so your agent can read them straight from node_modules/@devfamily/admiral/:

  • AI_GUIDE.md — an exact reference for generating Admiral code: the DataProvider contract and response shapes, where select/filter options come from, all 17 inputs, conditional-field rules, and the mistakes AI tools commonly make.
  • MIGRATION_AI.md — an executable v5 → v6 migration playbook.

The demo site also serves an index of these docs at admiral.dev.family/llms.txt.

Example prompt: "Read node_modules/@devfamily/admiral/AI_GUIDE.md, then add a CRUD page for the orders resource with a status filter and a conditional refund_reason field."

Contributing

Fork the repo, make your changes, and submit a pull request. We welcome contributions!

License

MIT © dev.family

Contact

Questions or feedback: [email protected]