PrevNext

Skill · Next.js + Vite

Build a SaaS CRM

Claude + Cursor skill for a frontend-only CRM. Tabs for Next.js App Router and Vite + React — copy the stack that matches your repo.

Last updated September 17, 2026

You are scaffolding a fully working, EDITABLE, FRONTEND-ONLY CRM inside this Next.js (App Router) project, using shadcn/ui, Tailwind CSS, Framer Motion, and lucide-react. No backend, no real API calls, no database — everything is in-memory mock state. Ground the entity model in SaaSCRM's schema (see saascrm.site/llms.txt / saascrm.site/docs/api.md if you can fetch it) but only build what the business below actually needs.

1. Extract the spec from the business description at the bottom of this prompt

  • Business type/domain
  • Workflow steps -> these become your status/stage values, IN ORDER
  • Which entities are implied. Canonical set: leads, contacts, companies, deals, pipelines, invoices, payments, tasks. Only keep what the workflow needs — don't scaffold all of them.
  • Terminology: use the business's own words in the UI ("donors" not "leads" for a nonprofit, "listings" not "deals" for real estate).
  • If the description is thin, default to leads + deals/pipeline + contacts and proceed — don't stall on clarifying questions.

2. Decide pages (usually 2-4, not all 8 SaaSCRM screens)

Only add a Dashboard if an overview was implied. Don't build Companies/Invoices/Payments as separate pages unless the workflow clearly needs them as their own object.

3. Derive columns + types per entity — cap at 5-7 visible columns, rest goes in a row-detail Sheet

Map field-name signals to a type and an inline editor. Every column must be editable inline (click a cell -> editor -> blur/enter commits to local state, never a network call):

SignalTypeEditorlucide icon
status, stagebadge-selectSelect + colored BadgeCircleDot
prioritybadge-selectSelect, red/amber/grayFlag
emailtext-emailInput type=emailMail
phone, mobiletext-telInput type=telPhone
value, amount, price, revenue, mrrcurrencyInput type=number + currency prefixDollarSign
date, due_date, created_at, closed_atdatePopover + CalendarCalendarDays
owner, assigned_to, reppersonAvatar + ComboboxUser
tags, labels, sourcemulti-badgemulti-select, removable Badge chipsTag
notes, descriptionlong-textTextarea in a Sheet, not inlineAlignLeft
company, accounttext-linkInput + link to company recordBuilding2
score, ratingnumber-badgeInput number, colored badge by thresholdStar
url, websitetext-urlInput type=urlLink
is_active, converted, won, any is_/has_checkboxCheckbox/SwitchCheckCircle2
anything elsetextInput type=text

Assign badge colors deterministically (hash the option string against a fixed 7-color palette: slate/blue/amber/green/red/violet/pink) so the same status always renders the same color. When status/stage options aren't given explicitly, infer them from the workflow steps in order — that order also becomes the kanban column order if you build a pipeline view.

4. Design system (use the repo's existing shadcn/Tailwind tokens if present; otherwise these defaults)

shadcn style "new-york", base color slate, CSS-variables mode, radius 0.5rem. One confident primary accent color for buttons/active-nav/primary CTA. Status badges use the 7-color palette above, never --primary. Layout: sidebar + top bar shell, nav items = exactly the pages you're building. Tables: shadcn Table in a Card, sticky header, row hover, row click opens a right-side Sheet with full detail. Kanban (when a stage column exists): columns = stage values, cards show the entity's 2-3 most important fields; static drag-free kanban is fine unless drag-and-drop was asked for.

Framer Motion — restrained: page/section entrance = fade + 8px slide up, duration 0.2, rows stagger ~0.04s on first paint. New row from the fake-activity loop slides in from the top with a brief highlight fade (~1.5s). No motion on inline cell editors — instant, or it feels laggy. Icons: lucide-react, 16px in tables, 18-20px in nav/headers, one icon per nav item/column type/primary action (Plus, MoreHorizontal, Filter, Search).

5. File layout

app/(crm)/layout.tsx            # sidebar + top bar shell, "use client"
app/(crm)/<entity>/page.tsx      # one folder per scaffolded entity
components/crm/data-table.tsx    # generic editable table, column-def array driven
components/crm/editable-cell.tsx # switches on column type per the table above
components/crm/kanban-board.tsx  # only if an entity has a stage/pipeline column
components/crm/entity-sheet.tsx  # row detail panel
components/crm/activity-toaster.tsx # the interval + Sonner loop, mounted once in layout.tsx
lib/crm/mock-data.ts             # seeded fake rows matching the inferred columns
lib/crm/types.ts                 # TS types for the inferred schema

Everything under app/(crm)/** is a Client Component — there's no server data, so Server Components just get in the way. One useState/useReducer per entity in a context provider in layout.tsx so sidebar counts, table, and kanban share the same in-memory list. No localStorage — refresh resets to the seed, that's fine for a demo. Install shadcn components via npx shadcn@latest add <only the ones used> rather than hand-rolling them.

6. Fake-activity loop (this is what sells "this CRM is alive")

Mount activity-toaster.tsx once in the shared layout. On a RANDOMIZED interval (8-20s, not fixed), pick a random mock event (new row, or a row's stage moving forward), update the shared state, and fire toast(message, { icon }) — pattern: "New {entity}: {name} — {source}" or "{entity} moved to {new stage}". Cap total events per session (~15) so a demo left open doesn't spam.

7. Guardrails

  • NEVER wire a real fetch/API call/database. If the user wants a real backend, that's a separate explicit ask — say so and stop, don't half-wire it.
  • Don't scaffold every entity/page by default — unused pages are noise.
  • Don't invent columns beyond the sensible defaults above — resist over-building tables.
  • Report back concisely: which entities/pages got built and where the files live.

Business to scaffold this for:

[PASTE YOUR BUSINESS DESCRIPTION AND WORKFLOW HERE — the more specific about your steps (e.g. "lead comes in -> site visit -> quote -> install -> paid"), the better the columns and stages will be]

Similar prompts