An open API service indexing awesome lists of open source software.

https://github.com/zuohuadong/svadmin

Headless admin framework for Svelte 5 — bring your own backend | 面向 Svelte 5 的 Headless 管理后台框架
https://github.com/zuohuadong/svadmin

admin admin-panel appwrite crud data-provider elysia headless pocketbase shadcn-svelte supabase svelte svelte5 tanstack-query typescript

Last synced: 19 days ago
JSON representation

Headless admin framework for Svelte 5 — bring your own backend | 面向 Svelte 5 的 Headless 管理后台框架

Awesome Lists containing this project

README

          

# svadmin

> Headless admin framework for Svelte 5 — bring your own backend
>
> 面向 Svelte 5 的 Headless 管理后台框架 — 自带后端适配

[![npm](https://img.shields.io/npm/v/@svadmin/core?color=ff3e00&label=npm)](https://www.npmjs.com/package/@svadmin/core)
[![license](https://img.shields.io/github/license/zuohuadong/svadmin)](LICENSE)

[English](#-features) | [中文](#-特性) | [📖 Documentation / 文档](https://svadmin.nestjs.cn)

---

## ✨ Features

- 🎯 **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
- 🛡️ **``** — 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 via `InferData`
- 🧰 **Helpers** — `unionFilters`, `unionSorters`, `file2Base64`, `getDefaultFilter`, `getDefaultSortOrder`, `generateDefaultDocumentTitle`
- 📤 **Data Transfer** — `useExport` / `useImport` for 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
- 🛡️ **``** — 根据认证状态条件渲染,支持 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`)
- 🧰 **工具函数** — `unionFilters`、`unionSorters`、`file2Base64`、`getDefaultFilter`、`getDefaultSortOrder`、`generateDefaultDocumentTitle`
- 📤 **数据导入导出** — `useExport` / `useImport`,支持 CSV 批量导入导出
- 🔄 **乐观更新** — 内置悲观 / 乐观 / 可撤销三种变更模式

## 📦 Packages / 包

### Core / 核心

| 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 工具集成 |

### Data Providers / 数据适配器

| 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 |

## 🚀 Quick Start / 快速开始

```bash
# Install
bun add @svadmin/core @svadmin/ui @svadmin/simple-rest
```

### One-Line Setup / 一行配置

```svelte

import { AdminApp } from '@svadmin/ui';
import { createSimpleRestDataProvider } from '@svadmin/simple-rest';
import { resources } from './resources';

const dataProvider = createSimpleRestDataProvider({
apiUrl: 'https://jsonplaceholder.typicode.com',
});

```

### Define Resources / 定义资源

```typescript
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" },
],
},
],
},
];
```

### With Supabase / 使用 Supabase

```svelte

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
);

{#snippet loginPage()}{/snippet}

```

### With SupaCloud Tasks / 使用 SupaCloud 任务增强

`@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` 提供任务能力接入。

```bash
bun add @svadmin/supabase @supabase/supabase-js @supacloud/js
```

```ts
import { 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 });
```

```ts
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);
```

```ts
const stop = taskLiveProvider.subscribe({
resource: 'tasks',
liveParams: { taskId: 'task_123' },
callback: (event) => {
console.log(event.payload);
},
});

stop();
```

### With Elysia (Type-Safe) / 使用 Elysia(端到端类型安全)

```typescript
// 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 {}
}

const dataProvider = createElysiaDataProvider("http://localhost:3000");
```

### Tailwind CSS v4 Integration / Tailwind CSS v4 集成

> **Important / 重要**: Tailwind CSS v4 does not scan `node_modules` by default. You **must** add `@source` directives so that utility classes used by `@svadmin/ui` components are generated.
>
> Tailwind CSS v4 默认不扫描 `node_modules`。你**必须**添加 `@source` 指令,否则 `@svadmin/ui` 组件使用的工具类不会被生成,导致布局完全错乱。

**1. Add `@source` to your CSS entry file / 在 CSS 入口文件中添加 `@source`:**

```css
/* 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 异常:

```typescript
// 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",
],
},
});
```

## 🏗️ `` 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` | — | — | Override default UI components / 覆盖默认组件 |

## 🌓 Dark Mode / 暗色模式

Dark mode works out of the box. Use `defaultTheme` prop or the Sidebar toggle:

暗色模式开箱即用。使用 `defaultTheme` prop 或侧边栏切换按钮:

```svelte

```

Programmatic control / 编程式控制:

```typescript
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'
```

## 🎨 Color Themes / 多色主题

Switch between 6 color palettes via sidebar picker or programmatically:

通过侧边栏选色器或编程式切换 6 种配色:

```typescript
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`

## 🏷️ Resource Type Registry / 资源类型注册表

For end-to-end type safety, register your resource types:

注册资源类型以获得端到端类型安全:

```typescript
// 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!
```

## 🔌 Custom DataProvider / 自定义数据源

Implement the `DataProvider` interface to connect any backend:

实现 `DataProvider` 接口即可接入任意后端:

```typescript
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 }) => {
/* ... */
},
};
```

## 🏗️ Architecture / 架构

```
┌──────────────────────────────────────────┐
│ 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 │
└──────────────────────────────────────────┘
```

## 📖 Documentation / 文档

Full documentation is available at / 完整文档请访问:

**[svadmin.nestjs.cn](https://svadmin.nestjs.cn)**

## 🤝 Contributing / 贡献

Contributions are welcome! 欢迎贡献!

1. Fork the repo
2. Create your branch (`git checkout -b feat/amazing-feature`)
3. Commit (`git commit -m 'feat: add amazing feature'`)
4. Push (`git push origin feat/amazing-feature`)
5. Open a Pull Request

## 📝 License

MIT