Headless admin framework for Svelte 5 — bring your own backend
面向 Svelte 5 的 Headless 管理后台框架 — 自带后端适配
English | 中文 | 📖 Documentation / 文档
useList, useOne, useCreate, useUpdate, useDelete, useTable, useForm, useSelect, useInfiniteList, useShow, useStepsForm, useModalForm, useDrawerForm, etc.useLogin, useLogout, useRegister, useForgotPassword, useUpdatePassword, useGetIdentity, useIsAuthenticated, useOnError, usePermissions<Authenticated> — Conditionally render based on auth state with loading/fallbackKnownResources + auto type inference via InferData<R>unionFilters, unionSorters, file2Base64, getDefaultFilter, getDefaultSortOrder, generateDefaultDocumentTitleuseExport / useImport for CSV export/import with batch supportuseList、useOne、useCreate、useUpdate、useDelete、useTable、useForm、useSelect、useInfiniteList、useShow、useStepsForm、useModalForm、useDrawerForm 等useLogin、useLogout、useRegister、useForgotPassword、useUpdatePassword、useGetIdentity、useIsAuthenticated、useOnError、usePermissions<Authenticated> — 根据认证状态条件渲染,支持 loading/fallbackKnownResources)+ 自动类型推断(InferData<R>)unionFilters、unionSorters、file2Base64、getDefaultFilter、getDefaultSortOrder、generateDefaultDocumentTitleuseExport / useImport,支持 CSV 批量导入导出| Package | Description / 描述 |
|---|---|
@svadmin/core |
Hooks, providers, types, utilities, Resource Type Registry |
@svadmin/ui |
Pre-built admin components / 预构建管理组件(shadcn-svelte) |
@svadmin/create |
CLI scaffolding tool / CLI 脚手架工具 |
| Package | Backend |
|---|---|
@svadmin/simple-rest |
REST API (zero deps, JWT/Cookie auth) |
@svadmin/supabase |
Supabase (data + auth + live) |
@svadmin/pocketbase |
PocketBase (data + auth + live) |
@svadmin/appwrite |
Appwrite (data + auth + live) |
@svadmin/graphql |
GraphQL |
@svadmin/elysia |
Elysia (auto type inference via Eden Treaty) |
@svadmin/strapi |
Strapi CMS |
@svadmin/directus |
Directus |
@svadmin/firebase |
Firebase / Firestore |
@svadmin/hasura |
Hasura GraphQL |
@svadmin/sanity |
Sanity.io |
@svadmin/airtable |
Airtable |
@svadmin/medusa |
Medusa Commerce |
@svadmin/nestjs-query |
NestJS GraphQL |
@svadmin/nestjsx-crud |
NestJS CRUD |
# Install
bun add @svadmin/core @svadmin/ui @svadmin/simple-rest
<script lang="ts">
import { AdminApp } from '@svadmin/ui';
import { createSimpleRestDataProvider } from '@svadmin/simple-rest';
import { resources } from './resources';
const dataProvider = createSimpleRestDataProvider({
apiUrl: 'https://jsonplaceholder.typicode.com',
});
</script>
<AdminApp {dataProvider} {resources} title="My Admin" defaultTheme="system" />
import type { ResourceDefinition } from '@svadmin/core';
export const resources: ResourceDefinition[] = [
{
name: 'products',
label: 'Products',
fields: [
{ key: 'id', label: 'ID', type: 'number', showInForm: false },
{ key: 'name', label: 'Name', type: 'text', required: true, searchable: true },
{ key: 'price', label: 'Price', type: 'number', required: true },
{ key: 'status', label: 'Status', type: 'select', options: [
{ label: 'Active', value: 'active' },
{ label: 'Draft', value: 'draft' },
]},
],
},
];
<script lang="ts">
import { AdminApp } from '@svadmin/ui';
import { createSupabaseDataProvider, createSupabaseAuthProvider } from '@svadmin/supabase';
import { createClient } from '@supabase/supabase-js';
import { resources } from './resources';
import Login from './pages/Login.svelte';
const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY
);
</script>
<AdminApp
dataProvider={createSupabaseDataProvider(supabase)}
authProvider={createSupabaseAuthProvider(supabase)}
{resources}
title="My App"
>
{#snippet loginPage()}<Login />{/snippet}
</AdminApp>
// Server: export your Elysia app type
import { Elysia } from 'elysia';
const app = new Elysia().get('/posts', () => db.posts.findMany());
export type App = typeof app;
// Client: auto-infer resource types
import { createElysiaDataProvider } from '@svadmin/elysia';
import type { InferResourceMap } from '@svadmin/elysia';
import type { App } from './server';
// ResourceTypeMap auto-derived from Elysia routes
declare module '@svadmin/core' {
interface ResourceTypeMap extends InferResourceMap<App> {}
}
const dataProvider = createElysiaDataProvider<App>('http://localhost:3000');
<AdminApp> Props| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
dataProvider |
DataProvider |
✅ | — | Data source adapter / 数据源适配器 |
authProvider |
AuthProvider |
— | — | Auth adapter / 认证适配器 |
routerProvider |
RouterProvider |
— | hash | Custom router / 自定义路由提供者 |
resources |
ResourceDefinition[] |
✅ | — | Resource definitions / 资源定义 |
title |
string |
— | 'Admin' |
App title / 应用标题 |
defaultTheme |
'light' | 'dark' | 'system' |
— | 'system' |
Initial theme / 初始主题 |
themeConfig |
ThemeConfig |
— | — | Theme config (strategy, overrides) / 主题配置 |
locale |
string |
— | auto | Override locale / 覆盖语言 |
dashboard |
Snippet |
— | — | Custom dashboard / 自定义仪表盘 |
loginPage |
Snippet |
— | — | Custom login page / 自定义登录页 |
components |
Partial<ComponentRegistry> |
— | — | Override default UI components / 覆盖默认组件 |
Dark mode works out of the box. Use defaultTheme prop or the Sidebar toggle:
暗色模式开箱即用。使用 defaultTheme prop 或侧边栏切换按钮:
<!-- Follow system / 跟随系统 -->
<AdminApp {dataProvider} {resources} defaultTheme="system" />
<!-- Always dark / 始终暗色 -->
<AdminApp {dataProvider} {resources} defaultTheme="dark" />
<!-- Dark-first strategy for dark-themed apps / 默认暗色的应用 -->
<AdminApp {dataProvider} {resources} themeConfig={{ strategy: 'dark-first' }} />
Programmatic control / 编程式控制:
import { setTheme, toggleTheme, getTheme, getResolvedTheme } from '@svadmin/core';
setTheme('dark'); // 'light' | 'dark' | 'system'
toggleTheme(); // toggle between light/dark
getTheme(); // current setting
getResolvedTheme(); // resolved to 'light' or 'dark'
Switch between 6 color palettes via sidebar picker or programmatically:
通过侧边栏选色器或编程式切换 6 种配色:
import { getColorTheme, setColorTheme, colorThemes } from '@svadmin/core';
import type { ColorTheme } from '@svadmin/core';
setColorTheme('rose'); // 'blue' | 'green' | 'rose' | 'orange' | 'violet' | 'zinc'
getColorTheme(); // current color theme
console.log(colorThemes); // [{ id: 'blue', label: 'Blue', color: '#3b82f6' }, ...]
Available themes / 可用主题: blue (default), green, rose, orange, violet, zinc
For end-to-end type safety, register your resource types:
注册资源类型以获得端到端类型安全:
// Extend the ResourceTypeMap interface (declaration merging)
declare module '@svadmin/core' {
interface ResourceTypeMap {
posts: { id: number; title: string; body: string };
users: { id: number; name: string; email: string };
}
}
// Now all hooks get compile-time checking:
useList({ resource: 'posts' }); // ✅ OK
useList({ resource: 'postz' }); // ❌ Compile error — typo caught!
Implement the DataProvider interface to connect any backend:
实现 DataProvider 接口即可接入任意后端:
import type { DataProvider, BaseRecord } from '@svadmin/core';
const myProvider: DataProvider = {
getApiUrl: () => 'https://api.example.com',
getList: async ({ resource, pagination, sorters, filters }) => { /* ... */ },
getOne: async ({ resource, id }) => { /* ... */ },
create: async ({ resource, variables }) => { /* ... */ },
update: async ({ resource, id, variables }) => { /* ... */ },
deleteOne: async ({ resource, id }) => { /* ... */ },
};
┌──────────────────────────────────────┐
│ Your App / 你的应用 │
│ (resources, pages, providers) │
├──────────────────────────────────────┤
│ @svadmin/ui │
│ AdminApp · AutoTable · AutoForm │
│ ShowPage · 16 Fields · shadcn-svelte│
├──────────────────────────────────────┤
│ @svadmin/core │
│ 30+ Hooks · Context · Router · i18n │
│ Permissions · Audit · Theme │
│ Resource Type Registry · Helpers │
├──────────┬───────────┬───────────────┤
│ /supabase│/simple-rest│ /pocketbase │
│ /appwrite│ /graphql │ /elysia ... │
└──────────┴───────────┴───────────────┘
Full documentation is available at / 完整文档请访问:
Contributions are welcome! 欢迎贡献!
git checkout -b feat/amazing-feature)git commit -m 'feat: add amazing feature')git push origin feat/amazing-feature)MIT