Skip to content
Framework: Vite + React + TypeScriptDifficulty: intermediate

CRM pipeline

Contacts table plus a five-stage deal pipeline board with inline stage changes, all persisted locally.

A small CRM with two views over the same data: a searchable contacts table with stage selects and delete, and a kanban-style pipeline (Lead → Qualified → Proposal → Won/Lost) where deals move between columns with keyboard-accessible buttons. State lives in localStorage via a typed hook so the app works offline; swap src/store.ts for API calls when you add a backend.

  • react
  • crm
  • pipeline
  • kanban
  • tailwind

This preview is the template's actual file tree and source code — exactly what is copied into a new project. Codexa does not publish screenshots or mock-ups of templates; run the project to see it rendered.

Files14 files

src/ContactsTable.tsx62 lines
import { useState } from "react";
import { STAGES, type Stage, type useContacts } from "./store";

export function ContactsTable({ store }: { store: ReturnType<typeof useContacts> }) {
  const [q, setQ] = useState("");
  const rows = store.contacts.filter((c) => [c.name, c.company, c.email].some((s) => s.toLowerCase().includes(q.toLowerCase())));
  return (
    <div className="rounded-xl border border-slate-200 bg-white">
      <div className="flex flex-wrap items-center justify-between gap-3 border-b border-slate-200 p-3">
        <input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search contacts" aria-label="Search contacts" className="rounded-md border border-slate-300 px-3 py-1.5 text-sm" />
        <button type="button" onClick={store.reset} className="text-xs text-slate-500 hover:text-slate-900">
          Reset sample data
        </button>
      </div>
      <div className="overflow-x-auto">
        <table className="w-full min-w-[640px] text-sm">
          <thead className="text-left text-slate-500">
            <tr>
              <th className="p-3">Name</th>
              <th className="p-3">Company</th>
              <th className="p-3">Email</th>
              <th className="p-3">Stage</th>
              <th className="p-3">Value</th>
              <th className="p-3">
                <span className="sr-only">Actions</span>
              </th>
            </tr>
          </thead>
          <tbody>
            {rows.map((c) => (
              <tr key={c.id} className="border-t border-slate-100">
                <td className="p-3 font-medium">{c.name}</td>
                <td className="p-3">{c.company}</td>
                <td className="p-3 text-slate-600">{c.email}</td>
                <td className="p-3">
                  <select value={c.stage} onChange={(e) => store.update(c.id, { stage: e.target.value as Stage })} aria-label={"Stage for " + c.name} className="rounded border border-slate-300 px-2 py-1">
                    {STAGES.map((s) => (
                      <option key={s}>{s}</option>
                    ))}
                  </select>
                </td>
                <td className="p-3">{"$" + c.value.toLocaleString()}</td>
                <td className="p-3 text-right">
                  <button type="button" onClick={() => store.remove(c.id)} className="text-xs text-red-600 hover:underline">
                    Delete
                  </button>
                </td>
              </tr>
            ))}
            {rows.length === 0 ? (
              <tr>
                <td colSpan={6} className="p-6 text-center text-slate-500">
                  No contacts found.
                </td>
              </tr>
            ) : null}
          </tbody>
        </table>
      </div>
    </div>
  );
}

Dependencies

Documented from the template's package.json. The runtime has a prebuilt dependency set for Vite + React + TypeScript, so installs are fast.

PackageVersion
react^19.1.0
react-dom^19.1.0
vite^6.3.0
@vitejs/plugin-react^4.4.0
tailwindcss^4.1.0
@tailwindcss/vite^4.1.0
typescript^5.8.0

How it runs

Framework
Vite + React + TypeScript
Dev command
npm run dev
Build command
npm run build
Output directory
dist
Port
5173
Opens at
/
Difficulty
intermediate

Projects run in an isolated sandbox with a live preview. Read the projects documentation for details on settings, snapshots and deployment.

Need the raw data? GET /api/v1/templates/vite-react-crm returns this template with its files.

Build on CRM pipeline

Create a free account, start from this template, and ask the AI agent to turn it into your app.