Skip to Content
CLI Commandsshadpanel resource

shadpanel resource

Generate list, create, edit, and view pages from a Prisma model. Resource 2.0 (CLI 1.6.0, PR #15 ) maps relations: belongsTo → FormSelect, hasMany/M2M → lists on the view page.

This is the hero path of ShadPanel:

shadpanel resource Post

Command

shadpanel resource <name> [options]

Alias: r

Arguments

  • <name> — model name, singular or plural (Post, posts, and post all resolve to the Post model)

Options

OptionDescription
--forceOverwrite existing files
--skip-menuDo not modify config/menu.ts
--path <projectPath>Target project (default: cwd)
--dry-runPreview would-create / would-skip / would-overwrite without writing

Default write policy is skip-if-exists (exit 0). Re-running without --force leaves existing pages in place.

Prerequisites

  1. prisma/schema.prisma must exist — otherwise exit 2 with Prisma not initialized (no crash)
  2. The model must be defined — otherwise exit 3 and the CLI lists available models
shadpanel db init # edit prisma/schema.prisma shadpanel db migrate make add_posts shadpanel db migrate run shadpanel resource Post

Resource 2.0 Field Mapping

Prisma typeWidget
StringFormInput (email / password by field name)
Int / Float / DecimalFormInput numeric
BooleanFormCheckbox
DateTimeFormDateTimePicker
enumFormSelect with static options
JsonFormTextarea
Bytesskipped (comment in the form)
@idskipped
belongsTo (n:1), e.g. Post.authorFormSelect of related records
covered FK (authorId when author exists)skipped — the belongsTo select writes the FK
lone FK scalar (roleId with no Role relation)scalar input (not M2M RBAC)
hasMany / implicit M2Mview/show list only — not a create/edit FormSelect

belongsTo labels use the first of name / title / email / label string scalars on the related model, else id.

Not in 1.6.0: Prisma 7, 2FA, per-resource policies, M2M RBAC widgets.

Generated Files

For shadpanel resource Post:

app/admin/dashboard/posts/ ├── actions.ts # "use server" — import prisma from '@/lib/prisma' ├── page.tsx # list + View / Edit / Delete ├── create/page.tsx ├── edit/[id]/page.tsx └── view/[id]/page.tsx # scalars + related lists lib/prisma.ts # emitted if missing (PrismaClient singleton) config/menu.ts # patched unless --skip-menu

getPost / getPostById include every relation field so the view page can list related rows.

belongsTo on create/edit

Post.author User @relation(fields: [authorId], references: [id]) becomes:

<FormSelect accessor='authorId' label='Author' options={userOptions} />

Actions also emit getUserOptions() (prisma.user.findMany({ take: 100 })). Numeric FKs are coerced with Number(...) on submit; empty string becomes null.

A lone User.roleId without a Role relation stays a numeric/string input.

View page

view/[id]/page.tsx shows scalar fields and, for hasMany / M2M, a list of related records (label from name / title / email / label, else id). The list page includes a View row action.

Example Schema

model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) tags Tag[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model User { id String @id email String name String posts Post[] } model Tag { id Int @id @default(autoincrement()) name String posts Post[] }
shadpanel resource Post

You get:

  • /admin/dashboard/posts — table of posts
  • /admin/dashboard/posts/create — title, content, published, Author select (not a raw authorId input)
  • /admin/dashboard/posts/edit/[id]
  • /admin/dashboard/posts/view/[id] — fields plus a Tags related list
  • Menu item under config/menu.ts

Server Actions

Generated actions import the singleton and revalidate the resource path:

"use server" import prisma from '@/lib/prisma' import { revalidatePath } from 'next/cache'

create / update cast form data to Prisma client input types so next build succeeds.

Unless --skip-menu, the CLI patches config/menu.ts (or creates a minimal file). Existing URLs are left alone.

Skip-if-exists

shadpanel resource Post # skip files that already exist shadpanel resource Post --force # overwrite shadpanel resource Post --dry-run # print would-create / would-skip / would-overwrite

See Also

Last updated on