admin-crud-page
Pattern for building admin dashboard pages using SvelteKit and remote functions.
Install
mkdir -p .claude/skills/admin-crud-page && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/6083" && unzip -o skill.zip -d .claude/skills/admin-crud-page && rm skill.zipInstalls to .claude/skills/admin-crud-page
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Create admin dashboard pages with tables, forms, and actionsKey capabilities
- →Create admin list pages with tables
- →Develop edit and create forms
- →Implement row actions and confirmation dialogs
- →Integrate status and type filters
- →Enforce remote function architecture
How it works
It uses a specific directory structure where all server-side logic is handled by .remote.ts files, and admin pages are built using pre-defined UI components like Table, PageHeader, and Actions.
Inputs & outputs
When to use admin-crud-page
- →Building a new admin dashboard section
- →Creating an admin list page with table actions
- →Developing edit/create forms for admin panels
About this skill
Admin CRUD Page Pattern
Use this skill when creating admin pages for managing entities.
When to Use
- Adding a new admin section (e.g., /admin/[feature])
- Creating admin list pages with tables and row actions
- Creating admin edit/create forms with headers
Note: For general page patterns (forms, filters, pagination, remote functions), see page-builder.
Route Structure
Admin routes live in src/routes/(admin)/admin/:
src/routes/(admin)/admin/
└── [feature]/
├── +page.svelte # List page (pure renderer)
├── data.remote.ts # Remote functions (all logic here)
├── [id]/
│ └── +page.svelte # Edit page
└── new/
└── +page.svelte # Create page (optional)
IMPORTANT: Never use
+page.server.tsThis project uses Remote Functions exclusively for server-side logic. All data loading, form handling, and mutations must go through
.remote.tsfiles. Never create+page.server.ts,+server.ts, or use SvelteKit form actions.
Admin-Specific Components
| Component | Purpose | Import |
|---|---|---|
PageHeader | Page title with icon and actions | $lib/ui/admin/PageHeader.svelte |
Table | Data table with snippets for header/row/actions | $lib/ui/admin/Table.svelte |
AdminList | Simple wrapper with title and "New" button | $lib/ui/admin/AdminList.svelte |
StatusSelect | Status filter dropdown | $lib/ui/admin/StatusSelect.svelte |
TypeSelect | Content type filter | $lib/ui/admin/TypeSelect.svelte |
Badge | Status/type badges | $lib/ui/admin/Badge.svelte |
Actions | Row action buttons (edit, delete, custom) | $lib/ui/admin/Actions |
ContentPicker | Select related content | $lib/ui/admin/ContentPicker.svelte |
QuickAction | Dashboard quick action cards | $lib/ui/admin/QuickAction.svelte |
ConfirmWithDialog | Confirmation dialog wrapper | $lib/ui/admin/ConfirmWithDialog.svelte |
Quick Start
List Page
<script lang="ts">
import PageHeader from '$lib/ui/admin/PageHeader.svelte'
import Table from '$lib/ui/admin/Table.svelte'
import { Actions, Action } from '$lib/ui/admin/Actions'
import FileText from 'phosphor-svelte/lib/FileText'
import { getItems, deleteItem } from './data.remote'
const items = await getItems()
</script>
<div class="container mx-auto space-y-8 px-2 py-6">
<PageHeader
title="Items"
description="Manage all items"
icon={FileText}
/>
<Table action={true} data={items}>
{#snippet header(classes)}
<th class={classes}>Name</th>
<th class={classes}>Status</th>
{/snippet}
{#snippet row(item, classes)}
<td class={classes}>{item.name}</td>
<td class={classes}>{item.status}</td>
{/snippet}
{#snippet actionCell(item)}
<Actions id={item.id}>
<Action.Edit href={`/admin/items/${item.id}`} />
<Action.Delete form={deleteItem} />
</Actions>
{/snippet}
</Table>
</div>
Edit Page
<script lang="ts">
import { page } from '$app/state'
import PageHeader from '$lib/ui/admin/PageHeader.svelte'
import { initForm } from '$lib/utils/form.svelte'
import { updateItem, getItem } from '../data.remote'
import FileText from 'phosphor-svelte/lib/FileText'
const itemId = page.params.id!
const item = await getItem({ id: itemId })
initForm(updateItem, () => ({
id: itemId,
name: item?.name ?? '',
status: item?.status ?? 'draft'
}))
</script>
<div class="container mx-auto space-y-8 px-2 py-6">
<PageHeader
title="Edit Item"
description="Update item settings"
icon={FileText}
/>
<form {...updateItem} class="space-y-6">
<input {...updateItem.fields.id.as('hidden', itemId)} />
<!-- See page-builder/DETAIL-PAGE.md for form patterns -->
<button type="submit">Save</button>
</form>
</div>
Authorization
Always call checkAdminAuth() first in admin remote functions:
import { checkAdminAuth } from '../authorization.remote'
export const getItems = query('unchecked', async (searchParams) => {
checkAdminAuth() // Throws if not admin
// ... rest of logic
})
Reference Files
- LIST-PAGE.md - Table, Actions, Badge patterns
- EDIT-PAGE.md - PageHeader, ConfirmWithDialog patterns
- TEMPLATES.md - Copy-paste starter templates
General Patterns
For patterns that apply to both admin and public pages, see:
- page-builder/LIST-PAGE.md - Filters, search, pagination
- page-builder/DETAIL-PAGE.md - Forms, validation
- page-builder/FEED-PAGE.md - Mixed-type feeds
- using-remote-functions/REMOTE-FIRST.md - Remote-first architecture
When not to use it
- →When creating public-facing pages
- →When using server-side files (+page.server.ts)
Prerequisites
Limitations
- →Strictly forbids +page.server.ts files
- →Requires use of remote functions for all logic
How it compares
It enforces a remote-first architecture for admin pages, strictly forbidding standard SvelteKit server-side files in favor of remote functions.
Compared to similar skills
admin-crud-page side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| admin-crud-page (this skill) | 1 | 7mo | No flags | Intermediate |
| svelte | 3 | 2mo | No flags | Intermediate |
| component-builder | 1 | 7mo | No flags | Beginner |
| svelte-ui-design | 23 | 9mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by svelte-society
View all by svelte-society →You might also like
svelte
EpicenterHQ
Svelte 5 patterns including TanStack Query mutations, shadcn-svelte components, and component composition. Use when writing Svelte components, using TanStack Query, or working with shadcn-svelte UI.
component-builder
svelte-society
Create UI components using tailwind-variants for type-safe styling. Use when creating or editing components in src/lib/ui/.
svelte-ui-design
XIYO
ALWAYS use this skill for ANY Svelte component styling, design, or UI work. Svelte 5 UI design system using Tailwind CSS 4, Skeleton Labs design tokens/presets/Tailwind Components, and Bits UI headless components. Covers class composition, color systems, interactive components, forms, overlays, and all visual design.
tanstack-form
exceptionless
TanStack Form with Zod validation in Svelte 5. Form state management, field validation, error handling, and ProblemDetails integration. Keywords: TanStack Form, createForm, Field, form validation, zod schema, form errors, onSubmit, onSubmitAsync, problemDetailsToFormErrors
tanstack-query
exceptionless
Data fetching and caching with TanStack Query in Svelte. Query patterns, mutations, cache invalidation, WebSocket-driven updates, and optimistic updates. Keywords: createQuery, createMutation, TanStack Query, query keys, cache invalidation, optimistic updates, refetch, stale time, @exceptionless/fetchclient, WebSocket
svelte-migrate
temporalio
Migrate a Svelte 4 component to Svelte 5 runes syntax. Use when asked to migrate, convert, or upgrade a .svelte file to Svelte 5.