Nexus CRM Documentation

Nexus CRM

A production-ready CRM dashboard template built with Next.js 16, TypeScript, Tailwind CSS v4, and shadcn/ui. Dark mode by default, fully responsive, and driven by realistic mock data so you can connect your own backend in minutes.

Template dashboard CRM siap produksi, dibikin pakai Next.js 16, TypeScript, Tailwind CSS v4, dan shadcn/ui. Dark mode by default, responsif penuh, dan datanya pakai mock data yang realistis — jadi kamu bisa sambungin ke backend sendiri cuma dalam hitungan menit.

Thank you for purchasing Nexus CRM! This document covers everything you need to install, customize, and ship the template. If you get stuck, jump to Support.

Makasih udah beli Nexus CRM! Dokumen ini ngebahas semua yang kamu butuhin buat install, custom, sampai rilis template-nya. Kalau ada yang nyangkut, langsung lompat ke bagian Bantuan.

FeaturesFitur

12+ pages12+ halamanDashboard, Leads, Deals, Contacts, Organizations, Notes, Tasks, Settings, Auth + detail views.Dashboard, Leads, Deals, Contacts, Organizations, Notes, Tasks, Settings, Auth + halaman detail.
Dark + Light modeDark + Light modeTheme toggle via next-themes, driven by CSS tokens.Toggle tema pakai next-themes, diatur lewat token CSS.
Fully typedFull TypeScriptTypeScript strict mode, zero any.Strict mode, nol any.
ResponsiveResponsifMobile, tablet, and desktop layouts.Rapi di mobile, tablet, dan desktop.
InteractiveInteraktifEditable Notes & Tasks, filterable tables, Kanban board.Notes & Tasks bisa diedit, tabel yang bisa difilter, board Kanban.
ChartsChartRevenue, deal stage, win/loss — theme-aware Recharts.Revenue, stage deal, win/loss — Recharts yang ngikut tema.
Self-contained avatarsAvatar mandiriInline SVG, no network requests.SVG inline, tanpa request jaringan.
Subtle motionAnimasi halusFramer Motion transitions.Transisi pakai Framer Motion.

RequirementsKebutuhan

  • Node.js ≥ 20 (LTS recommended)
  • pnpm ≥ 9 — install with npm install -g pnpm
  • A modern browser (Chrome, Firefox, Safari, Edge)
  • Node.js ≥ 20 (mending versi LTS)
  • pnpm ≥ 9 — install pakai npm install -g pnpm
  • Browser modern (Chrome, Firefox, Safari, Edge)

Using npm / yarn / bun? The project ships with pnpm, but any package manager works — delete pnpm-lock.yaml and install with your tool of choice.

Pakai npm / yarn / bun? Default-nya emang pnpm, tapi package manager apa aja bisa kok — hapus pnpm-lock.yaml-nya, terus install pakai tool favoritmu.

Quick StartMulai Cepat

# 1. Install dependencies
pnpm install

# 2. Start the dev server
pnpm dev
# → http://localhost:3000  (redirects to /dashboard)

# 3. Production build
pnpm build
pnpm start
# 1. Install dependency
pnpm install

# 2. Jalanin dev server
pnpm dev
# → http://localhost:3000  (otomatis diarahin ke /dashboard)

# 3. Build produksi
pnpm build
pnpm start

Available scriptsDaftar script

ScriptScriptDescriptionFungsinya
pnpm devStart the dev server (Turbopack)Jalanin dev server (Turbopack)
pnpm buildProduction buildBuild buat produksi
pnpm startServe the production buildJalanin hasil build produksi
pnpm lintRun ESLintJalanin ESLint

No configuration needed to run. The template ships with mock data and requires no environment variables. Install, run, done.

Nggak perlu setting apa-apa buat jalan. Template-nya udah pakai mock data dan nggak butuh environment variable sama sekali. Install, jalanin, kelar.

Tech Stack

LayerBagianTechnologyTeknologi
FrameworkNext.js 16 (App Router)
LanguageBahasaTypeScript 5 (strict)
StylingTailwind CSS v4 + tw-animate-css
UI primitivesKomponen UIshadcn/ui (Radix UI)
ChartsChartRecharts 3
AnimationAnimasiFramer Motion 12
IconsIkonLucide React
ThemingTemanext-themes
ToastSonner
Package managerpnpm

Project StructureStruktur Project

src/
├── app/
│   ├── (auth)/                 # Auth layout group
│   │   ├── login/
│   │   └── register/
│   ├── (dashboard)/            # App layout group (sidebar + header)
│   │   ├── layout.tsx          # Sidebar + Header wrapper
│   │   ├── dashboard/
│   │   ├── leads/  + [id]/     # Kanban + lead detail
│   │   ├── deals/  + [id]/
│   │   ├── contacts/ + [id]/
│   │   ├── organizations/ + [id]/
│   │   ├── notes/
│   │   ├── tasks/
│   │   ├── notifications/
│   │   └── settings/
│   ├── globals.css             # Design tokens + Tailwind theme
│   ├── layout.tsx              # Root layout (fonts, ThemeProvider, Toaster)
│   └── page.tsx                # Redirect → /dashboard
│
├── components/
│   ├── ui/                     # shadcn/ui primitives
│   ├── shared/                 # Reusable app components (PageHeader, StatusBadge…)
│   ├── layout/                 # Sidebar, Header
│   ├── charts/                 # Recharts wrappers
│   └── [feature]/              # Page-specific components (contacts/, tasks/…)
│
├── lib/
│   ├── mock-data.ts            # ALL mock data + accessor helpers
│   ├── format.ts               # formatCurrency, formatDate, getInitials…
│   ├── nav.ts                  # Sidebar navigation config
│   └── utils.ts                # cn() classname helper
│
└── types/
    └── index.ts                # ALL TypeScript interfaces

The two files you'll touch most: src/lib/mock-data.ts (data) and src/types/index.ts (shapes).

Dua file yang paling sering kamu utak-atik: src/lib/mock-data.ts (datanya) dan src/types/index.ts (tipe datanya).

CustomizationKustomisasi

Colors & themeWarna & tema

All colors are CSS custom properties in src/app/globals.css. Edit the :root block (light mode) and the .dark block (dark mode) — nothing else references raw hex values.

Semua warna disimpan sebagai CSS custom property di src/app/globals.css. Edit blok :root (light mode) dan blok .dark (dark mode) — nggak ada tempat lain yang nyimpen nilai hex langsung.

:root {
  --primary: #3b82f6;        /* accent (blue-500) */
  --primary-hover: #2563eb;
  --background: #ffffff;
  --foreground: #111827;
  /* … */
}
.dark {
  --background: #0a0a0a;
  --foreground: #f9fafb;
  /* … */
}

Change --primary to rebrand the entire app in one line.

Ganti --primary aja, dan brand seluruh aplikasi langsung berubah cuma dari satu baris.

FontsFont

Fonts are loaded in src/app/layout.tsx via next/font/google (Geist Sans + Geist Mono). Swap them for any Google or local font there.

Font di-load di src/app/layout.tsx lewat next/font/google (Geist Sans + Geist Mono). Mau ganti ke font Google lain atau font lokal? Ubah di situ.

Sidebar navigationMenu sidebar

Edit src/lib/nav.ts — add, remove, or reorder items. Each item is { label, href, icon } using a Lucide icon. Header page titles are derived from this file automatically.

Edit src/lib/nav.ts — mau nambah, hapus, atau ubah urutan menu tinggal di sini. Tiap item bentuknya { label, href, icon } pakai ikon Lucide. Judul halaman di header otomatis ngikut file ini.

export const mainNav: NavItem[] = [
  { label: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
  { label: "Leads", href: "/leads", icon: UserPlus },
  // …
];

Adding a new pageNambah halaman baru

  1. Create src/app/(dashboard)/your-page/page.tsx.
  2. Add an entry to mainNav in src/lib/nav.ts.
  3. Build page-specific components under src/components/your-page/.
  1. Bikin src/app/(dashboard)/your-page/page.tsx.
  2. Tambahin entri ke mainNav di src/lib/nav.ts.
  3. Taruh komponen khusus halaman itu di src/components/your-page/.

Avatar

Avatars are generated locally as inline SVG data URIs (gradient + initials) by the avatar() function in src/lib/mock-data.ts. No network requests — they render offline. To use real photos, drop images in /public/avatars/ and return their paths from avatar().

Avatar dibikin lokal sebagai SVG data URI inline (gradient + inisial) lewat fungsi avatar() di src/lib/mock-data.ts. Nggak ada request jaringan — tetap muncul walau offline. Kalau mau pakai foto asli, taruh gambarnya di /public/avatars/, terus return path-nya dari avatar().

Mock Data → Real APIMock Data → API Asli

Everything renders from src/lib/mock-data.ts — there are no live API calls anywhere. All shapes are defined in src/types/index.ts, so your API just needs to return matching JSON. Components import mock data directly today. The migration is the same everywhere: fetch on the server, pass data down as props.

Semua tampilan dirender dari src/lib/mock-data.tsnggak ada panggilan API beneran sama sekali. Semua tipe data udah didefinisiin di src/types/index.ts, jadi API kamu tinggal balikin JSON yang bentuknya sama. Sekarang komponen masih import mock data langsung. Pola pindahnya sama semua: fetch di server, terus lempar datanya sebagai props.

Pattern A — Server Components (list & detail pages)Pola A — Server Component (halaman list & detail)

Pages like contacts/page.tsx are async-capable Server Components. Lift the data import up to the page as a fetch, then pass it into the presentational component as a prop.

Halaman kayak contacts/page.tsx itu Server Component yang bisa async. Pindahin import datanya ke halaman jadi fetch, terus lempar ke komponen tampilannya sebagai prop.

// src/app/(dashboard)/contacts/page.tsx
import type { Contact } from "@/types";
import { ContactsTable } from "@/components/contacts/contacts-table";

async function getContacts(): Promise<Contact[]> {
  const res = await fetch(`${process.env.API_URL}/contacts`, {
    next: { revalidate: 60 }, // ISR — or cache: "no-store"
  });
  if (!res.ok) throw new Error("Failed to load contacts");
  return res.json();
}

const ContactsPage = async () => {
  const contacts = await getContacts();
  return <ContactsTable contacts={contacts} />;
};

Recommended: a thin data layer. Create src/lib/api/ functions that mirror the helper names already in mock-data.ts (getContact, getOrganizationDeals, …). Then swapping mock → real is a one-line import change per page.

Saran: bikin data layer tipis. Bikin fungsi di src/lib/api/ yang namanya niru helper yang udah ada di mock-data.ts (getContact, getOrganizationDeals, …). Jadi ganti dari mock ke API asli cukup ubah satu baris import per halaman.

Pattern B — Client Components (Notes, Tasks, filterable tables)Pola B — Client Component (Notes, Tasks, tabel berfilter)

Components marked "use client" (e.g. tasks/task-list.tsx) seed React state from mock data:

Komponen yang ada "use client"-nya (misal tasks/task-list.tsx) ngisi state React dari mock data:

const [tasks, setTasks] = useState<Task[]>(initialTasks);

For these, either pass the initial data as props from an async parent Server Component (preferred), or fetch on the client with SWR / React Query and persist mutations through Server Actions. The CRUD handlers already exist (save, remove, toggle) — replace the setState calls with your API mutation plus an optimistic update.

Buat kasus ini, lempar data awalnya sebagai props dari Server Component induk yang async (paling recommended), atau fetch di client pakai SWR / React Query dan simpan perubahannya lewat Server Actions. Handler CRUD-nya udah ada (save, remove, toggle) — tinggal ganti setState-nya jadi mutasi API kamu plus optimistic update.

The data contractKontrak data

EntityEntitasTypeTipeMock exportExport mock
ContactsContactcontacts, getContact
LeadsLeadleads, getLead
DealsDealdeals, getDeal
OrganizationsOrganizationorganizations, getOrganization
NotesNotenotes
TasksTasktasks
Users / teamUser / timUsercurrentUser, teamMembers
Dashboard metricsMetrik dashboardMetricdashboardMetrics

Environment variables

Copy .env.example to .env.local and fill in your values:

Copy .env.example jadi .env.local, terus isi nilainya:

API_URL=https://api.yourbackend.com

Deployment

Standard Next.js app — deploys anywhere Node runs.

Aplikasi Next.js biasa — bisa di-deploy di mana aja yang bisa jalanin Node.

  • Vercel (recommended): import the repo, it auto-detects Next.js. Zero config.
  • Netlify / Cloudflare / Render: use the Next.js adapter/preset.
  • Self-host / Docker: pnpm build then pnpm start behind a reverse proxy.
  • Vercel (paling gampang): tinggal import repo-nya, Next.js kedeteksi otomatis. Zero config.
  • Netlify / Cloudflare / Render: pakai adapter/preset Next.js.
  • Self-host / Docker: pnpm build terus pnpm start di belakang reverse proxy.

Set any environment variables in your host's dashboard.

Set environment variable-nya di dashboard hosting kamu.

Credits & Third-Party LicensesKredit & Lisensi Pihak Ketiga

All third-party packages are open source and permissively licensed. No attribution is required in your end product; they are listed here for transparency.

Semua paket pihak ketiga open source dan lisensinya permisif. Nggak wajib nyantumin atribusi di produk akhirmu; daftar ini cuma buat transparansi.

Asset / LibraryAset / LibraryLicenseLisensi
Next.js, React, React DOMMIT
Radix UI / shadcn/uiMIT
RechartsMIT
Framer MotionMIT
Sonner, next-themes, clsx, tailwind-mergeMIT
Tailwind CSS, tw-animate-cssMIT
class-variance-authorityApache-2.0
Lucide iconsISC
Geist Sans / Geist Mono (fonts)SIL Open Font License 1.1

Avatars are 100% self-contained. Generated locally as inline SVG data URIs — no external services, no network requests, no attribution needed.

Avatar 100% mandiri. Dibikin lokal sebagai SVG data URI inline — tanpa layanan eksternal, tanpa request jaringan, dan nggak perlu atribusi.

Changelog

v1.0.0 Initial releaseRilis pertama

  • First public release.
  • Rilis publik pertama.

SupportBantuan

For questions, bug reports, or customization help, contact:

Buat pertanyaan, laporan bug, atau bantuan kustomisasi, hubungi:

your-support-email@example.com

Please include your purchase code and a clear description (screenshots help). We aim to respond within 1–2 business days.

Sertakan kode pembelian dan jelasin masalahnya sejelas mungkin (screenshot sangat membantu). Kami usahain bales dalam 1–2 hari kerja.