Desi Stack
HomeHomeProjectsProjectsCoursesCoursesGamesGamesPricingPricingServicesServicesContactContact
Get Started

Desi Stack

Empowering developers with production-ready projects, comprehensive courses, and professional services. Learn, build, and launch your next big idea.

contact@desistack.com
India

Product

  • Projects
  • Courses
  • Services

Company

  • About
  • Contact
  • Blog

Resources

  • Course Materials
  • FAQs
  • Support

Legal

  • Privacy Policy
  • Refund Policy
  • Terms of Service
Follow our journey

© 2026 Desi Stack. Made with in India

Subscribe
All posts
adminuxnextjs

How We Structure Admin Forms

Desi Stack17 Jul 20263 min read

Admin UX is part of the product

If publishing a blog post or creating a course feels fragile, you will stop updating the site. Customers never see that friction — they only see silence.

So we treat admin forms like production UI: predictable, validated, and fast to navigate.

The Desi Stack pattern

1. Server page.tsx owns loading data

Example: edit blog loads the post by id, 404s if missing, passes serializable initial props into the form.

Server code stays free of useState. It can talk to Prisma directly and keep secrets off the wire.

2. Client form owns interaction

BlogForm, CourseForm, ProjectForm handle:

  • Controlled fields
  • Auto-slug from title
  • Write / preview tabs for Markdown
  • Upload vs URL modes for media
  • Toasts + disable states while saving

For huge wizards (projects), a Zustand store can hold multi-step state without prop-drilling hell. For blogs, a single page form is enough — do not cargo-cult five steps.

3. API routes validate with Zod

Never trust the browser. The admin API:

  • Calls checkAdminAccess()
  • Parses the body with Zod
  • Normalizes tags/slugs
  • Computes derived fields (reading time)
  • revalidatePath for public pages after mutate

Errors return clear JSON the form can toast.

4. Media goes through a dedicated upload route

MediaUploadField posts to /api/admin/upload with a folder like blogs. The form stores the returned URL — not a File object in the database.

That keeps Postgres lean and CDN/storage where it belongs.

List pages that do not feel frozen

Admin navigation used to feel blank while heavy server pages awaited. We fix that with:

  • loading.tsx skeletons per segment
  • Client tables that filter quickly after initial data
  • Avoiding 13 sequential queries on every click when a lighter query will do

Trust is: click → immediate feedback → content.

Draft / publish as a first-class state

Content features need more than “save.”

For blogs we use draft | published | archived:

  • Drafts never hit public routes
  • Publish sets publishedAt on first publish
  • Archive hides without deleting history
  • Delete is confirm-modal only

Courses/projects can mirror the same mindset with status fields and explicit buttons.

Checklist for a new admin resource

  1. Prisma model + migration
  2. GET/POST list+create admin API, GET/PUT/DELETE by id
  3. /admin/<resource> table + loading.tsx
  4. new + [id]/edit pages with shared form component
  5. Sidebar link
  6. Public routes if the resource is public-facing
  7. Seed script data living under src/data/

If any of those are missing, you will feel it during the second week of use.

What we refuse to overbuild in v1

  • Block editors when Markdown is enough
  • Soft realtime collaboration in admin
  • Ten-step wizards for three fields
  • Client-only “security”

Ship the boring CRUD that lets you publish daily. Decorate later.

See it live

Create or edit posts at /admin/blogs. The public side is /blog. Same pattern powers courses and projects across the panel.

Keep building

Related reads

Browse projects →
nextjsreact

Next.js App Router: Mental Model in 10 Minutes

Server Components, client boundaries, layouts, and route handlers — a clear mental model so you stop guessing where "use client" belongs.

20 Jul 20263 min