Documentation
Frontend Generator

Frontend Generator

omni-rest scaffolds a complete React data layer for every model β€” TanStack Query hooks, TanStack Table columns, DataTable components, and FormGenerator components β€” all wired to your omni-rest API.

⚠️

v0.4.0 introduces a new two-package workflow. The recommended approach is omni-rest generate:config (backend) + omni-rest-client generate:frontend (frontend). The old npx omni-rest generate:frontend still works but is legacy.


Recommended workflow (v0.4.0+)

The frontend generator is now split into two lightweight CLIs:

Backend (omni-rest)                    Frontend (omni-rest-client)
────────────────────────────           ──────────────────────────────────
npx omni-rest generate:config    β†’     npx omni-rest-client generate:frontend
  writes omni-rest.config.json           reads omni-rest.config.json
  (models + Zod schemas)                 writes hooks, components, pages
  Prisma-aware                           Zero Prisma dependency

Why the split?

  • Frontend project no longer needs @prisma/client installed
  • Config file is plain JSON β€” easy to commit, share, or pipe through CI
  • Both CLIs stay focused and lightweight

See the full guide: omni-rest-client β†’


Legacy: generate:frontend

The original command still works if you prefer running everything from the backend project:

npx omni-rest generate:frontend

Prerequisites

npm install @tanstack/react-query @tanstack/react-table react-hook-form zod @hookform/resolvers
npx prisma generate
npx omni-rest generate

Running

npx omni-rest generate:frontend

Auto-detects your frontend directory and framework, then prompts per model.


What gets generated

For a User model:

      • useUser.ts
        • UserColumns.tsx
        • UserTable.tsx
        • UserForm.tsx
      • data-table.tsx
      • form-generator.tsx
      • providers.tsx
      • menu-data.ts
        • page.tsx

  • Using the generated components

    // app/users/page.tsx
    import { UserTable } from '@/src/components/user/UserTable'
     
    export default function UsersPage() {
      return (
        <div className="container mx-auto py-10">
          <h1 className="text-3xl font-bold mb-6">Users</h1>
          <UserTable />
        </div>
      )
    }

    Add the providers wrapper to your layout:

    // app/layout.tsx
    import { Providers } from '@/src/components/providers'
     
    export default function RootLayout({ children }: { children: React.ReactNode }) {
      return (
        <html>
          <body>
            <Providers>{children}</Providers>
          </body>
        </html>
      )
    }

    Framework detection

    SignalDetected framework
    next.config.js / next.config.ts presentnextjs
    vite.config.ts / vite.config.js presentvite-react
    react in package.jsonreact

    When framework is nextjs, every generated .tsx file gets 'use client' as its first line.


    Multi-step forms

    When a model has more than 6 fields, the form is automatically split into wizard steps (max 4 fields per step):

    npx omni-rest generate:frontend --steps always   # always multi-step
    npx omni-rest generate:frontend --steps never    # never multi-step
    npx omni-rest generate:frontend --steps auto     # default

    Flags reference

    FlagDefaultDescription
    --schema <path>auto-discoverPath to schema.prisma
    --frontend-dir <path>auto-scanFrontend project root
    --out <dir>src/Output directory
    --models <names>allComma-separated model names
    --autopilotfalseSkip all prompts
    --no-bulkβ€”Disable bulk delete
    --no-optimisticβ€”Disable optimistic updates
    --no-pagesβ€”Disable Next.js page generation
    --no-menuβ€”Disable menu-data.ts
    --route-group <name>autogenerated-omniRoute group name
    --stale-time <ms>30000TanStack Query staleTime
    --gc-time <ms>300000TanStack Query gcTime
    --steps <mode>autoauto | always | never
    --helpβ€”Print usage

    Re-running after schema changes

    npx prisma generate
    npx omni-rest generate
    npx omni-rest generate:frontend --autopilot

    Hook and column files are overwritten on each run. Base components are skipped if they already exist.