A AdminPro
Documentation

Introduction

What's in the box, and how this documentation is organized.

AdminPro is an HTML, CSS and vanilla JavaScript admin dashboard template. It ships as two complete layouts — a collapsible left sidebar and a horizontal top navigation — covering 29 unique page templates each, plus a shared design system so both layouts always look and behave consistently.

There's no build step, no framework and no package manager involved. Every page is a plain .html file you can open directly in a browser, edit in any code editor, and deploy to any static host.

New here? Start with Installation, then read Sidebar vs. horizontal to decide which shell to build on before you start customizing pages.

Installation

There's nothing to install — open it and go.

  1. Unzip the package you downloaded.
  2. Open landing.html in a browser to see the overview page, or open any page inside sidebar/ or horizontal/ directly.
  3. To deploy, upload the whole folder to any static host (Netlify, Vercel, S3, cPanel, GitHub Pages) — no server-side runtime is required.

Use a local server while editing, if you can. Every page works fine opened directly from disk (file://). If you later add features that fetch() local JSON files, browsers block that over file:// — running a simple local server (e.g. the VS Code "Live Server" extension, or python3 -m http.server) avoids the issue.

Requirements

  • Any modern code editor (VS Code, Sublime, etc.) — no IDE-specific setup needed.
  • An evergreen browser (Chrome, Edge, Firefox, Safari) for previewing.
  • An internet connection on first load, for the Google Fonts, Bootstrap Icons and Chart.js CDN links — see Credits to self-host them instead.

Folder structure

Where everything lives in the package.

/
├── landing.html — overview page with both live previews
├── documentation.html — this file
│
├── sidebar/ — left-sidebar layout
│   ├── index.html, analytics.html, orders.html, …
│   └── assets/
│      ├── css/  style.css, orders.css, users.css, …
│      └── js/   script.js, orders.js, users.js, …
│
└── horizontal/ — horizontal-nav layout
    ├── dashboard-horizontal.html, analytics-horizontal.html, …
    └── assets/
       ├── css/  style.css, orders-horizontal.css, …
       └── js/   script.js, orders-horizontal.js, …

The two layouts are self-contained. sidebar/ and horizontal/ each have their own style.css and script.js — they're not shared between the two folders, because each layout's shared script exposes slightly different behavior (see JavaScript architecture). If you only need one layout, you can delete the other folder entirely.

Sidebar vs. horizontal

Both cover the same 29 pages with the same components — the difference is purely navigational.

LayoutNavigationBest forEntry point
SidebarCollapsible left sidebar, with sub-menu drill-downApps with deep, hierarchical navigationsidebar/index.html
HorizontalTop nav bar, scrolls on narrow screensWide tables and chart-heavy screenshorizontal/dashboard-horizontal.html

Every other page name in horizontal/ matches its sidebar/ counterpart with a -horizontal suffix — for example sidebar/orders.html and horizontal/orders-horizontal.html are the same screen, built on each shell.

CSS architecture

One shared stylesheet, one small file per page.

Each layout folder's assets/css/style.css holds everything shared across every page: CSS custom properties (colors, radius, shadow, spacing), resets, typography, the sidebar/nav shell, buttons, cards, badges, tables, avatars and the preloader.

Every page then loads one additional, small CSS file with only what's unique to that page — for example orders.css holds just the order-status colors and the stock-badge styling that orders.html needs.

<!-- in orders.html -->
<link rel="stylesheet" href="assets/css/style.css">
<link rel="stylesheet" href="assets/css/orders.css">

Naming convention

A page's own CSS file always matches its HTML filename: settings.html → assets/css/settings.css, orders-horizontal.html → assets/css/orders-horizontal.css. If a page needs no unique styling at all (like the dashboard, which is built entirely from shared components), it simply doesn't load a page CSS file.

CSS custom properties

Every color, radius and shadow in the template is a variable, defined once in style.css:

VariableLight valueUsed for
--ap-primary#4F46E5Brand color — buttons, links, active states
--ap-success#16A34APositive status, growth indicators
--ap-warning#F59E0BPending / low-stock status
--ap-danger#DC2626Errors, destructive actions
--ap-info#0EA5E9Informational badges, secondary chart series
--ap-surface#FFFFFFCard and panel backgrounds
--ap-bg#F5F7FBPage background
--ap-text / --ap-text-strong#475569 / #0F172ABody text / headings
--ap-border#E7EBF1Card borders, dividers
--ap-radius / --ap-radius-sm0.75rem / 0.5remCard / control corner radius

To rebrand the template, change the --ap-primary group in style.css — every button, active nav item and focus ring updates automatically, in both light and dark mode.

JavaScript architecture

One shared script, one small file per page — mirroring the CSS.

assets/js/script.js runs on every page and handles the behavior that's identical everywhere:

  • Fixing dropdown menus so they aren't clipped inside scrollable tables
  • Sidebar collapse (desktop) and slide-out drawer (mobile)
  • Sidebar sub-menu expand/collapse (sidebar layout only)
  • Light/dark theme toggle
  • Fullscreen toggle
  • Hiding the preloader once the page has loaded

Each page then loads one page-specific file — orders.js, users.js, and so on — containing only the data and logic that page needs: table rendering, search/filter/pagination, and any Chart.js instances.

<!-- always in this order, at the end of the page -->
<script src="assets/js/script.js"></script>
<script src="assets/js/orders.js"></script>

Keep script.js first. Page scripts read variables like shell and root that script.js declares. Loading a page script before script.js, or removing script.js, will throw a ReferenceError.

Colors & dark mode

Both driven by the same set of CSS variables — nothing to duplicate.

Dark mode is not a second set of pages or a separate stylesheet. It's the same variables, redefined once inside a [data-theme="dark"] block:

:root {
  --ap-surface: #FFFFFF;
  --ap-bg: #F5F7FB;
  --ap-text: #475569;
}

[data-theme="dark"] {
  --ap-surface: #151B2C;
  --ap-bg: #0B1120;
  --ap-text: #93A0B8;
}

Clicking the theme toggle in the topbar sets data-theme="dark" on the <html> element; every component repaints instantly because it was already reading from the variables above. To make dark mode the default, set data-theme="dark" directly on the <html> tag in your HTML.

Working with charts

Chart.js instances that already know about light and dark mode.

Chart-heavy pages define a small themeColors() helper that reads the current theme and returns a matching color set, and a drawAllCharts() function that destroys and rebuilds every chart on the page:

function themeColors() {
  const dark = root.getAttribute('data-theme') === 'dark';
  return {
    grid: dark ? 'rgba(255,255,255,.06)' : 'rgba(15,23,42,.06)',
    text: dark ? '#93A0B8' : '#64748B',
    primary: '#4F46E5', info: '#0EA5E9'
  };
}

drawAllCharts() is called once on page load, again whenever the theme toggle is clicked, and again whenever a chart's range buttons (Week / Month / Year) are clicked — so any chart you add following the same pattern gets theme-switching and range-switching for free.

Point-style legends (the small circular markers) all use a shared generateLabels override that adds spacing between the dot and the label text. Copy that pattern when adding a new chart with usePointStyle: true so its legend matches the rest of the template.

Replacing demo data

Every table, chart and list runs on a plain JavaScript array — swap it for a real API call.

Data lives at the top of each page's own JS file as a plain array of objects, for example in orders.js:

const orders = [
  { id: '#ORD-4821', name: 'Meera Shah', amount: '$248.00', status: 'success' },
  // …
];

The rest of the file reads from that array to render rows, filter, sort and paginate. To connect a real backend, replace the array with the result of a fetch() call and call the existing render function once the response arrives — the rendering, search and pagination logic don't need to change.

Page reference

Every page, and where to find it in each layout.

Dashboardindex.html / dashboard-horizontal.html
Analyticsanalytics.html
CRMcrm.html
E-Commerceecommerce.html
Graphsgraphs.html
Reportsreports.html
Calendarcalendar.html
Emailemail.html
Messagesmessages.html
Projectsprojects.html
Invoicesinvoices.html
Billingbilling.html
Productsproducts.html
Product detailsproduct-details.html
Ordersorders.html
Customerscustomers.html
Customer detailscustomer-details.html
Usersusers.html
Profileprofile.html
Settingssettings.html
UI elementsui-elements.html
Extended UIextended-ui.html
Iconsicons.html
Modalsmodals.html
Notificationsnotifications.html
Data tablesdata-tables.html
Form elementsform-elements.html
Form validationform-validation.html
Authenticationauth.html
Lock screen*lock-screen.html
404 / 500 error*404.html / 500.html

In horizontal/, every filename above (except auth.html) carries a -horizontal suffix. *Lock screen and error pages ship in sidebar/ only, since they're standalone screens with no navigation shell.

Browser support

Tested on the latest evergreen browsers.

BrowserSupport
Chrome / Edge (Chromium)Fully supported
FirefoxFully supported
Safari (macOS & iOS)Fully supported
Internet Explorer 11Not supported (uses CSS custom properties and modern JS)

Credits

Third-party resources used, and where they're loaded from.

ResourceUsed forLoaded via
Bootstrap 5.3.8Grid, layout utilities, base componentsCDN / local assets/css+js
Bootstrap Icons 1.11All icons throughout the templateCDN
Chart.js 4All charts (line, bar, doughnut, sparklines)CDN / local assets/js
Google Fonts — InterUI and body typefaceCDN
Google Fonts — Roboto MonoOrder IDs, SKUs, invoice numbers, code blocksCDN
i.pravatar.cc / picsum.photosPlaceholder avatars and product photos in demo dataRemote images — replace with your own before going live

Want to work offline? Bootstrap and Chart.js already ship locally in assets/css and assets/js in most pages — swap any remaining CDN <link>/<script> tag for Bootstrap Icons and Google Fonts with a self-hosted copy to remove the last external requests.

FAQ

Common questions before and after purchase.

Yes — delete whichever of sidebar/ or horizontal/ you don't need. They don't share files, so removing one won't affect the other.

Copy the closest existing page as a starting point, keep its <link>/<script> order intact (shared style.css/script.js first, then a new page-specific CSS/JS file named to match), and swap the content inside .ap-main.

Almost always a missing or misordered script tag — double-check assets/js/script.js is loaded, and loaded before your page's own script, as shown in JavaScript architecture.

Yes. See Replacing demo data — every table and chart reads from a plain JavaScript array that you can populate from an API response instead.

Changelog

Version history for this item.

VersionNotes
1.0.0Initial release — sidebar and horizontal layouts, 29 pages each, light/dark mode, documentation.