Headless admin framework for Svelte 5 — bring your own backend
面向 Svelte 5 的 Headless 管理后台框架 — 自带后端适配
English | 中文 | 📖 Documentation / 文档
- 🎯 Headless Architecture — DataProvider / AuthProvider / RouterProvider / LiveProvider, swap backends freely
- ⚡ 30+ Reactive Hooks —
useList,useOne,useCreate,useUpdate,useDelete,useTable,useForm,useSelect,useInfiniteList,useShow,useStepsForm,useModalForm,useDrawerForm, etc. - 🔑 Auth Hooks —
useLogin,useLogout,useRegister,useForgotPassword,useUpdatePassword,useGetIdentity,useIsAuthenticated,useOnError,usePermissions - 🧩 Pre-built UI — AdminApp, AutoTable, AutoForm, ShowPage, Sidebar, Layout, StepsForm, CommandPalette, Sheet, Drawer, Collapsible, Tooltip (shadcn-svelte)
- 🔠 16 Field Components — TextField, UrlField, EmailField, BooleanField, TagField, FileField, ImageField, MarkdownField, RichTextField, SelectField, MultiSelectField, RelationField, JsonField, ComboboxField, PasswordInput
- 🔘 CRUD Buttons — CreateButton, EditButton, DeleteButton, ShowButton, ListButton, RefreshButton, ExportButton, ImportButton, SaveButton, CloneButton
- 🛡️
<Authenticated>— Conditionally render based on auth state with loading/fallback - ⚙️ ConfigErrorScreen — Glassmorphism screen for missing env vars with copy-to-clipboard
- 🌍 i18n — Built-in zh-CN/en with browser auto-detection, one-click locale toggle
- 🔐 Auth & RBAC — AuthProvider + permission system with resource-level access control
- 🌓 Dark Mode — Light / Dark / System with one-click toggle, persisted to localStorage
- 🎨 Multi-Color Themes — 6 color palettes (Blue, Green, Rose, Orange, Violet, Zinc) with sidebar picker
- 🪟 Glassmorphism UI — Translucent sidebar with backdrop blur for a premium look
- 📡 Real-time — LiveProvider interface with WebSocket & SSE built-in providers
- 🔀 RouterProvider — Pluggable routing with hash and history router providers
- 📋 Audit Logging — Pluggable audit handler for tracking admin operations
- 🔍 Inferencer — Auto-generate admin UI from sample data or OpenAPI 3.x specs
- 🏷️ Resource Type Registry — Compile-time resource name checking via
KnownResources+ auto type inference viaInferData<R> - 🧰 Helpers —
unionFilters,unionSorters,file2Base64,getDefaultFilter,getDefaultSortOrder,generateDefaultDocumentTitle - 📤 Data Transfer —
useExport/useImportfor CSV export/import with batch support - 🔄 Optimistic Updates — Built-in pessimistic / optimistic / undoable mutation modes
- 🎯 Headless 架构 — DataProvider / AuthProvider / RouterProvider / LiveProvider,自由切换后端
- ⚡ 30+ 响应式 Hook —
useList、useOne、useCreate、useUpdate、useDelete、useTable、useForm、useSelect、useInfiniteList、useShow、useStepsForm、useModalForm、useDrawerForm等 - 🔑 Auth Hooks —
useLogin、useLogout、useRegister、useForgotPassword、useUpdatePassword、useGetIdentity、useIsAuthenticated、useOnError、usePermissions - 🧩 开箱即用 UI — AdminApp、AutoTable、AutoForm、ShowPage、Sidebar、Layout、StepsForm、CommandPalette、Sheet、Drawer、Collapsible、Tooltip(基于 shadcn-svelte)
- 🔠 16 种字段组件 — TextField、UrlField、EmailField、BooleanField、TagField、FileField、ImageField、MarkdownField、RichTextField、SelectField、MultiSelectField、RelationField、JsonField、ComboboxField、PasswordInput
- 🔘 CRUD 按钮 — CreateButton、EditButton、DeleteButton、ShowButton、ListButton、RefreshButton、ExportButton、ImportButton、SaveButton、CloneButton
- 🛡️
<Authenticated>— 根据认证状态条件渲染,支持 loading/fallback - ⚙️ ConfigErrorScreen — 环境变量缺失提示页,毛玻璃风格,支持一键复制
- 🌍 国际化 — 内置中英文,浏览器自动检测,侧边栏一键切换语言
- 🔐 认证与权限 — AuthProvider + 资源级权限控制
- 🌓 暗色模式 — 亮色 / 暗色 / 跟随系统,一键切换,持久化到 localStorage
- 🎨 多色主题 — 6 种配色方案(Blue、Green、Rose、Orange、Violet、Zinc),侧边栏选色器切换
- 🪟 毛玻璃 UI — 半透明侧边栏 + 背景模糊,质感拉满
- 📡 实时订阅 — LiveProvider 接口,内置 WebSocket 及 SSE 实现,自动重连
- 🔀 RouterProvider — 可插拔路由,内置 Hash 和 History 路由
- 📋 审计日志 — 可插拔的审计处理器
- 🔍 推断器(Inferencer) — 从样本数据或 OpenAPI 3.x 自动生成管理 UI
- 🏷️ 资源类型注册表 — 编译时资源名检查(
KnownResources)+ 自动类型推断(InferData<R>) - 🧰 工具函数 —
unionFilters、unionSorters、file2Base64、getDefaultFilter、getDefaultSortOrder、generateDefaultDocumentTitle - 📤 数据导入导出 —
useExport/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 脚手架工具 |
@svadmin/refine-adapter |
Bridge any @refinedev/* data provider to svadmin / 桥接 Refine 生态数据源 |
@svadmin/sveltekit |
SvelteKit router integration / SvelteKit 路由集成 |
@svadmin/lite |
SSR-only variant (no client JS) / 纯 SSR 变体 |
@svadmin/sso |
OIDC/OAuth2 SSO plugin / 单点登录插件 |
@svadmin/editor |
Rich-text editor component / 富文本编辑器组件 |
@svadmin/mcp |
MCP (Model Context Protocol) integration / AI 工具集成 |
| Package | Backend |
|---|---|
@svadmin/simple-rest |
REST API (zero deps, JWT/Cookie auth) |
@svadmin/supabase |
Supabase (data + auth + live) |
@svadmin/drizzle |
Drizzle ORM (SQLite, PostgreSQL, MySQL, D1) |
@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,
createSupabaseLiveProvider,
} 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)}
liveProvider={createSupabaseLiveProvider(supabase)}
{resources}
title="My App"
>
{#snippet loginPage()}<Login />{/snippet}
</AdminApp>@supacloud/js does not replace @supabase/supabase-js. It wraps a normal Supabase client and adds task-oriented platform APIs. @svadmin/supabase keeps the official Supabase adapters unchanged and exposes the optional @svadmin/supabase/supacloud subpath for these task features.
@supacloud/js 不是 @supabase/supabase-js 的替代品,而是建立在官方 Supabase 客户端之上的平台增强层。@svadmin/supabase 会继续保持官方 Supabase 适配器不变,并通过可选子路径 @svadmin/supabase/supacloud 提供任务能力接入。
bun add @svadmin/supabase @supabase/supabase-js @supacloud/jsimport { createClient } from '@supabase/supabase-js';
import { createSupaCloudClient } from '@supacloud/js';
import {
createSupaCloudTaskProvider,
createSupaCloudTaskLiveProvider,
} from '@svadmin/supabase/supacloud';
const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY,
);
const supacloud = createSupaCloudClient({
supabase,
managementApiUrl: import.meta.env.VITE_SUPACLOUD_API_URL,
projectRef: import.meta.env.VITE_SUPACLOUD_PROJECT_REF,
});
const taskProvider = createSupaCloudTaskProvider({ supacloud });
const taskLiveProvider = createSupaCloudTaskLiveProvider({ supacloud });const task = await taskProvider.submit('aorist-ai/generate/crop', {
body: { image_id: 'img_123' },
idempotencyKey: 'crop-img_123-v1',
});
const finalState = await task.wait();
console.log(finalState.status);const stop = taskLiveProvider.subscribe({
resource: 'tasks',
liveParams: { taskId: 'task_123' },
callback: (event) => {
console.log(event.payload);
},
});
stop();// 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");Important / 重要: Tailwind CSS v4 does not scan
node_modulesby default. You must add@sourcedirectives so that utility classes used by@svadmin/uicomponents are generated.Tailwind CSS v4 默认不扫描
node_modules。你必须添加@source指令,否则@svadmin/ui组件使用的工具类不会被生成,导致布局完全错乱。
1. Add @source to your CSS entry file / 在 CSS 入口文件中添加 @source:
/* app.css */
@import "tailwindcss";
/* Required: tell Tailwind v4 to scan svadmin component sources */
@source "../node_modules/@svadmin/ui/src";
@source "../node_modules/@svadmin/core/src";2. Configure Vite optimizeDeps / 配置 Vite optimizeDeps:
Since @svadmin/ui ships raw .svelte source files (not pre-built), exclude the svadmin packages from pre-bundling and explicitly include their CJS peer dependencies. If you use @svadmin/supabase in a Vite app, make sure it is also listed in optimizeDeps.exclude, otherwise Vite may pre-bundle it and throw dev-time optional-peer/export errors such as createRefineAdapter not being found:
由于 @svadmin/ui 提供的是原始 .svelte 源码文件(非预构建),需要将 svadmin 包排除在预打包之外,并显式包含其 CJS 对等依赖。如果你的 Vite 项目使用了 @svadmin/supabase,也必须把它加入 optimizeDeps.exclude;否则 Vite 可能错误预打包它,并在开发环境里抛出 createRefineAdapter 找不到之类的 optional-peer/export 异常:
// vite.config.ts
export default defineConfig({
optimizeDeps: {
exclude: ["@svadmin/core", "@svadmin/ui", "@svadmin/supabase"],
include: [
"@svadmin/core > @tanstack/svelte-query",
"@svadmin/ui > svelte-sonner",
"@svadmin/ui > vaul-svelte",
"@svadmin/ui > cmdk-sv",
"@svadmin/ui > bits-ui",
"@svadmin/ui > @tanstack/svelte-table",
"@svadmin/ui > @lucide/svelte",
"highlight.js",
"marked",
"marked-highlight",
"isomorphic-dompurify",
],
},
});| 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│ /drizzle │ /simple-rest │
│ /appwrite│ /graphql │ /elysia │
│ /firebase│ /hasura │ /pocketbase ... │
├──────────┴───────────┴───────────────────┤
│ @svadmin/refine-adapter │
│ Bridge any @refinedev/* provider │
└──────────────────────────────────────────┘
Full documentation is available at / 完整文档请访问:
Contributions are welcome! 欢迎贡献!
- Fork the repo
- Create your branch (
git checkout -b feat/amazing-feature) - Commit (
git commit -m 'feat: add amazing feature') - Push (
git push origin feat/amazing-feature) - Open a Pull Request
MIT