Architecture
CoolAdmin is a Bootstrap 5 + vanilla JavaScript admin template. 35 static HTML pages ship pre-built so end users can clone and open index.html with no Node required. Contributors get a Pug + SCSS source pipeline with a Vite dev server.
Last updated May 22, 2026
CoolAdmin’s design has two distinct audiences:
- End users clone the repo and open
index.html. The 35 HTML files at the root are real, committed artifacts — they work without npm install. - Contributors edit Pug templates and SCSS partials under
src/, then run a build that regenerates those same root*.htmlandcss/*.cssfiles.
Both modes ship together. There is no dist/ directory; the “build artifacts” are the repo.
File layout
CoolAdmin/
├── *.html # 35 pages — built artifacts (committed)
│ ├── index.html # Operations dashboard
│ ├── index2.html # Sales pipeline
│ ├── index3.html # Marketing analytics
│ ├── index4.html # Projects dashboard
│ ├── inbox.html / kanban.html / calendar.html / data-table.html
│ └── …
├── css/
│ ├── theme.css # Legacy stylesheet (~188 KB, ~12.3k lines)
│ ├── app.css # Modern overlay (~188 KB, ~8.5k lines), opt-in via body.app
│ └── font-face.css # Poppins font-face declarations
├── js/
│ ├── vanilla-utils.js # jQuery-shaped shim ($, $$, on, ready, …)
│ ├── bootstrap5-init.js # Tooltips + popovers only (everything else self-instantiates)
│ ├── main-vanilla.js # Chart configs + sidebar/dropdown/UI behaviors + ⌘K + theme switcher + toast
│ └── modern-plugins.js # Counters, modern progress bars, lightbox
├── vendor/ # Bootstrap, Chart.js, FullCalendar, Font Awesome (vendored)
├── images/
├── src/ # Source for contributors
│ ├── pug/
│ │ ├── layouts/ # _default, _auth, _error
│ │ ├── partials/ # _head, _nav-data, sidebar, header-desktop, footer-scripts
│ │ ├── partials/content/ # Per-page inner HTML (35 fragments)
│ │ └── pages/ # 35 Pug pages — one per route
│ └── scss/
│ ├── theme.scss + 20 ITCSS partials → css/theme.css
│ └── app.scss + 36 partials under app/ → css/app.css
├── scripts/
│ ├── build-pug.js # Walks src/pug/pages/, renders each to root *.html
│ └── migrate-page.js # Convert a root HTML file back into Pug (v3.2 migration helper)
├── package.json
└── vite.config.js # Dev server only — no production bundling
The two-stylesheet system
The most distinctive thing about CoolAdmin v3 is that it ships two complete design systems side by side:
css/theme.css— the original CoolAdmin design. Loaded on every page. Wraps everything in standard cascade — no special body class needed.css/app.css— the 2026 modern overlay. Activated by<body class="app">. Establishes a fresh design system (Inter font, brand-blue palette, modern cards, kanban, email reader, theme switcher).
Every demo page in the repo opts in via body.app. If you want the legacy design, remove the class — theme.css keeps working on its own.
The migration story: an existing CoolAdmin v2 user can pull v3.3 and their pages keep their old look because theme.css is unchanged. Adding class="app" to one page lets them try the new design on that page only. Migrating the whole app means setting class="app" on every page.
Script load order
Every page loads scripts at the bottom of <body> in this exact order. Later files depend on globals from earlier ones, so don’t shuffle:
<script src="js/vanilla-utils.js"></script>
<script src="vendor/bootstrap-5.3.8.bundle.min.js"></script>
<script src="vendor/chartjs/chart.umd.js-4.5.1.min.js"></script>
<script src="js/bootstrap5-init.js"></script>
<script src="js/main-vanilla.js"></script>
<script src="js/modern-plugins.js"></script>
vanilla-utils.jsmust load first — defines globals ($,$$,on,addClass,ready, …) used by every other file- Bootstrap bundle — provides
window.bootstrap(modals, dropdowns, collapse — self-instantiated viadata-bs-toggle) - Chart.js UMD bundle — note the
.umdin the filename. Don’t swap to the ES module build; pages load scripts as classic<script>not modules, and the ES build will throw “Cannot use import statement outside a module” bootstrap5-init.jsexplicitly instantiates only tooltips and popovers (those don’t self-instantiate). Everything else usesdata-bs-toggleand works without manual initmain-vanilla.js— Chart.js configs, sidebar/dropdown/hamburger UI, ⌘K palette, theme switcher, toast system. Charts usewithCanvas(id, fn)guards so the file is safe to include on pages without those canvasesmodern-plugins.js— counters, modern progress bars, lightbox
Per-page additions:
map.htmlandindex2.htmlload Leaflet fromunpkg.com(CDN, with SRI)calendar.htmlloads FullCalendar as an additional vendor scriptchart.htmlloads no extras — Chart.js is already in the base set
The shell — sidebar + topbar + content
Every default-layout page follows the same skeleton:
<body class="app" data-page="dashboard">
<a href="#main-content" class="visually-hidden-focusable skip-link">Skip to main content</a>
<aside class="sidebar">
<!-- rendered by src/pug/partials/sidebar.pug at build time -->
</aside>
<header class="header-desktop">
<!-- topbar: search, dropdowns, account menu -->
</header>
<main id="main-content" class="main-content">
<!-- page-specific markup -->
</main>
</body>
The sidebar and topbar render at build time from Pug templates — they’re plain HTML in the final output, not runtime-injected. That means search engines see the full navigation on first paint and there’s no client-side render step.
The sidebar’s active state is set by the Pug build based on each page’s activePage local variable. Edit _nav-data.pug once, every page rebuilds with the new menu.
JS architecture conventions
- No jQuery.
vanilla-utils.jsprovides a jQuery-shaped shim. Use$,$$,on,addClass,removeClass,slideUp/slideDown,readyinstead of writing raw DOM — keeps the existing code idiomatic. - No module bundler for JS. Plain
<script>tags, globals onwindow. Vite is dev-only — it serves the static HTML with HMR for SCSS/Pug changes, but doesn’t bundle the runtime JS into chunks. - Bootstrap 5 components self-instantiate. Don’t
new bootstrap.Modal(el)unless you need programmatic control. Thedata-bs-toggleattribute pattern is enough. - Chart factory pattern. New charts in
main-vanilla.jsusewithCanvas(id, fn)to guard against missing canvases, and reusesparklineOptions()/lightTooltip/percentTooltip()for shared chart config. See Charts for details. - No
console.login shipped code. The v3.0 audit pass stripped all 35 calls; don’t reintroduce them. - Font Awesome 7 only —
fa-solid fa-*/fa-regular fa-*. Legacyfa fa-*,fas fa-*,-osuffix, andzmdi-*were all removed.
What was removed in v3.0
The v3.0 audit pass (May 2026) dropped ~260 KB of unused JS per page:
- AOS — scroll animations, never instantiated
- Perfect Scrollbar — replaced with native browser scrollbars styled via CSS (the
.js-scrollbar1class is now markup-only and harmless) - Swiper — touch sliders, never instantiated
- Material Iconic Font (
zmdi-*) — replaced by Font Awesome 7 across all 353 icon usages - 718 obsolete vendor-prefix declarations in CSS —
-webkit-border-radius, etc., all dead
theme.css shrank by 33 KB just from the CSS sweep. The remaining -webkit-* rules are all live ones (scrollbars, font-smoothing, placeholder pseudo-aliases).
See also
- Pug + SCSS pipeline — how the source pipeline works and how to add a new page
- Theming — design tokens, the
body.appoverlay, dark mode hook - Charts — the Chart.js factory pattern
- Deployment — shipping the static build