Quick start

CoolAdmin is a static HTML template — no build step, no toolchain. Open any .html file via a local server and you’re running.

# Clone or download the template
git clone https://github.com/puikinsh/CoolAdmin.git
cd CoolAdmin

# Serve locally (Python 3 example)
python3 -m http.server 8000

# Or with Node
npx serve .

Then visit http://localhost:8000/index.html. CSS is shipped pre-built — no Sass watcher to run.

Important

Open files via a local server, not file://. Some browsers block JavaScript and CSS loading from the file:// protocol for security reasons.

Contributor workflow

Use Node ≥22.12 to edit the Pug and SCSS sources. Built pages still run without Node.

npm ci
npm run dev       # Pug + Sass watchers, Vite at localhost:3000
npm run build     # minified calendar assets + HTML + CSS
npm test          # six Node regression tests
npm run check     # build and tests

Edit src/pug/pages/, shared templates in src/pug/partials/, and styles in src/scss/. Commit generated HTML/CSS with the source changes. Pug saves are debounced; unchanged pages are not rewritten.

v3.5.0 uses Vite 8.3.4, Sass 1.105.1, concurrently 10.0.6, Pug 3.0.4, Chokidar 5.0.0, and Terser 5.51.2. FullCalendar 7.1.2 runs on the calendar page; Chart.js 4.5.1 loads only on the five pages with chart canvases.

The calendar scripts shrink from 803 KB to 341 KB raw (165 KB to 96 KB gzip). Removing Chart.js avoids a 208 KB script request on 23 pages. Dashboard refresh releases old chart instances before replacing canvases. These are asset-size measurements, not page-speed scores.

CI checks Node 22/24, local assets, chart loading, calendar versions, Pug builds/watchers, chart cleanup, and generated output consistency. See the testing guide and release notes.

File structure

cooladmin/
├── *.html                    35 generated pages (dashboards, tables, forms, etc.)
├── css/
│   ├── theme.css             legacy CoolAdmin styles (kept for compat)
│   ├── app.css        modern v3 design system
│   └── font-face.css         Poppins font-face declarations
├── js/
│   ├── vanilla-utils.js      jQuery shim ($, on, ready, etc.)
│   ├── bootstrap5-init.js    Bootstrap 5 component init
│   ├── main-vanilla.js       chart configs + UI behaviors + JS APIs
│   └── modern-plugins.js     counters, lightbox, progress
├── vendor/                   third-party CSS/JS
│   ├── bootstrap-5.3.8.bundle.min.js
│   ├── fontawesome-7.3.1/
│   ├── chartjs/
│   └── fullcalendar-7.1.2/
├── src/pug/                  page templates and shared partials
├── src/scss/                 theme and app style sources
├── test/                     Node regression tests
├── scripts/                  Pug and vendor build helpers
├── images/                   logos, avatars, backgrounds
└── README.md

Every page links the same canonical CSS chain in this order:

  1. css/font-face.css — Poppins (legacy)
  2. https://rsms.me/inter/inter.css — Inter (the modern font)
  3. vendor/fontawesome-7.3.1/css/all.min.css — icons
  4. vendor/bootstrap-5.3.8.min.css — Bootstrap base
  5. css/theme.css — legacy theme
  6. css/app.css — modern overlay (this is where almost everything lives)

Color themes

Six accent-color presets ship out of the box. Use the floating palette button (bottom-right of any page) to try them, or set the body class directly:

<body class="app theme-purple">

Available themes: theme-blue (default), theme-purple, theme-teal, theme-rose, theme-amber, theme-graphite.

To define your own theme, override the four accent variables on body.app.theme-yourname:

body.app.theme-mycolor {
    --m-accent:        #ff5722;
    --m-accent-rgb:    255, 87, 34;
    --m-accent-hover:  #e64a19;
    --m-accent-soft:   #fff3e0;
}

The user’s choice is persisted automatically in localStorage under the key cooladmin.theme.

Typography

The default sans-serif is Inter served from rsms.me. The legacy Poppins is also bundled in fonts/poppins for offline use.

To swap fonts globally, change --m-font in src/scss/app/_variables.scss and run npm run build:sass:

body.app {
    --m-font: "Your Font", system-ui, sans-serif;
}

The type scale used across pages:

ElementSizeWeight
Page header h122 px600
Card title14 px600
Body14 px400
Subtitle / muted13 px400
KPI value26 px600 (tabular)
Eyebrow / label11 px600 uppercase

Components

Modern reusable patterns live under .m-* class names in app.css:

ClassPurpose
.m-cardWhite surface with header / body / footer
.m-btnModern button (with --primary, --ghost)
.m-tableBorderless table with hover rows
.stat-cardKPI tile with label, value, delta, sparkline
.profile-cardUser card with avatar, name, role, socials
.cover-cardCard with image cover + body
.pricing-cardPricing tier card with --featured
.notice-cardInline alert card (info / success / warning / danger)
.rank-listNumbered list with bars (top-N rankings)
.empty-state"No data" placeholder with icon + title
.skeletonLoading placeholder (with shimmer)

JavaScript APIs

Toast notifications

The toast system is auto-initialized on every page. Trigger it from anywhere:

// Simple
toast.success('Saved');
toast.info('Heads up');
toast.warning('Storage almost full');
toast.error('Something went wrong');

// Full options
toast.show({
    title: 'New version',
    message: 'v3.1.0 is now live',
    type: 'success',
    duration: 6000,    // ms; 0 = no auto-dismiss
});

Command palette

Press ⌘K (or CtrlK) anywhere to open. Programmatic control:

window.cmdk.open();
window.cmdk.close();

To add new commands, edit the COMMANDS array in js/main-vanilla.js:

{ section: 'Pages', title: 'My new page', sub: 'Custom workflow',
  href: 'my-page.html', icon: 'fa-bolt' }

Theme switcher

The floating palette button auto-injects on every page. The user’s choice is persisted in localStorage. To force a theme programmatically, just toggle the body class:

document.body.classList.remove('theme-blue', 'theme-purple', 'theme-teal',
                                'theme-rose', 'theme-amber', 'theme-graphite');
document.body.classList.add('theme-purple');

Chart configurations

Charts use Chart.js 4.5. Shared helpers in main-vanilla.js keep configs DRY:

  • withCanvas(id, fn) — safe per-canvas init (skips if canvas isn’t on the page)
  • kpiSparkline(ctx, opts) — gradient-fill sparkline for KPI tiles
  • sparklineOptions(), lightTooltip, modernTooltip — reusable option blocks

To add a new chart, append a withCanvas block:

withCanvas('my-chart', (ctx) => {
    new Chart(ctx, {
        type: 'line',
        data: { /* ... */ },
        options: { ...sparklineOptions(), /* overrides */ },
    });
});

Adding a new page

  1. Create src/pug/pages/my-page.pug from an existing page entry and update its metadata and activePage.
  2. Add markup to src/pug/partials/content/my-page.html and include it from the page entry.
  3. Add sidebar/mobile navigation in src/pug/partials/_nav-data.pug.
  4. Add any palette entry separately to COMMANDS in js/main-vanilla.js.
  5. Run npm run check and commit both sources and generated files.

Dark mode

Dark-mode tokens are pre-wired but not enabled by default. To enable, set data-bs-theme="dark" on the <html> element:

<html lang="en" data-bs-theme="dark">

The :root tokens swap to dark surfaces (--m-bg, --m-surface, --m-text, etc.). Note: a few legacy CoolAdmin styles still use hardcoded colors — a thorough dark pass is on the roadmap for v3.1.

Deployment

Publish only built HTML, CSS, JS, vendor libraries, fonts, images, and required media to a static host. Keep source files, node_modules, Git metadata, and credentials out of the public directory:

  • Netlify / Vercel: drag-and-drop the folder, no build command needed
  • Cloudflare Pages: deploy the staged runtime directory
  • GitHub Pages: push the repo, publish a staged runtime directory from your chosen branch
  • S3 + CloudFront: sync to a bucket with public-read
  • Plain shared hosting: FTP / rsync the folder up

Inter loads from rsms.me; the map page also uses Leaflet CDN assets and external map tiles. Self-host those assets and provide an appropriate tile source if offline use is required. Forms, authentication, payments, and data persistence require your own backend.

Tip

Strip unused vendor folders before deploy if you don’t need them — for example, drop fullcalendar-7.1.2 if you don’t use the calendar page (removes the calendar scripts and styles).