GitHub Copilot Instructions
May 20, 2026 · View on GitHub
Admin dashboard template (4.0.0) by Colorlib. 58 server-rendered HTML pages in production/, built with Vite 8 (Rolldown). Vanilla ES2022, no Bootstrap, no jQuery, no SPA framework. SCSS only. Heavyweight deps — ECharts 6, DataTables.net 2, Leaflet 1.9 — are lazy-imported per page. Full reference: CLAUDE.md.
Hard rules
- Vanilla DOM only.
querySelector,classList,addEventListener. No jQuery, no SPA framework. v4's pitch is "vanilla and small." - Single entry:
src/main-v4.js. Page-specific modules are lazy-imported inside it, guarded by DOM presence. Don't add<script>tags per page. - Pages auto-discover. Drop
production/<slug>.htmlanddiscoverEntries()invite.config.jspicks it up — never editrollupOptions.input. - Shell opt-in:
<body data-shell="admin" data-page="<key>" data-breadcrumb="Home > …">. The Vite plugin inlines sidebar/topbar/footer at build/dev time (no FOUC). - NAV is one constant —
NAVinsrc/v4/shell-render.js, 7 groups.keymatchesdata-page. New icons go in theICONSobject in the same file. - Overlays go through helpers:
showModal()/showToast()/openMenu()/openPanel()fromsrc/v4/{modal,toast,menus}.js. Never hand-roll a backdrop, escape handler, or focus return. - CSS custom properties for colors. Tokens in
src/scss/v4/_tokens.scssunder:rootand[data-theme="dark"]. Charts read them viagetComputedStyle(document.documentElement).getPropertyValue('--…')so dark-mode redraw is automatic. - Lazy ECharts. Match the modular import pattern in
src/v4/charts.js. Don'timport * as echarts. - Subpath-safe URLs.
import.meta.env.BASE_URLin JS,${base}in the Vite plugin, relative paths inproduction/*.html. Never hard-code a leading/. - Idempotent
init<Name>()exports. Every module insrc/v4/has one. Safe to call when its root element is absent, safe to call twice. - No
console.*in shipped code. Terser drops them in production; ESLint flags earlier. - Service worker only in prod (
import.meta.env.PRODguard) — keeps HMR working in dev.
File layout
src/main-v4.js— entry; mounts shell + lazy-loads page modulessrc/scss/v4/— 10 SCSS partials (_tokens,_layout,_components,_widgets,_forms,_datatable,_pages,_apps,_auth,main)src/v4/shell.js—mountShell()runtime (sidebar accordion, theme toggle, mobile drawer)src/v4/shell-render.js—NAV+ICONS+ pure renderers (also imported by Vite plugin)src/v4/charts.js—initCharts()+ ECharts factoriessrc/v4/tables.js—initTables()+ DataTables wrappersrc/v4/command-palette.js— ⌘Ksrc/v4/{modal,toast,menus}.js— overlay helperssrc/v4/{inbox,kanban,calendar,settings,file-manager}.js— page modules (lazy-loaded)src/v4/form-controls.js— date range, multi-select, rich textproduction/— 58 HTML entry pages, auto-discoveredpublic/— static assets copied verbatim todist/types/gentelella.d.ts— TypeScript declarations for the public JS surfacescripts/new-page.mjs— page scaffolder (npm run new -- <slug>)scripts/deploy-preview.sh— R2 deploy with per-file cache headers
Anti-patterns
- Don't add jQuery, Bootstrap, or a SPA framework.
- Don't write Vite entry input lists by hand.
- Don't add
<script>tags toproduction/*.htmlfor new modules — lazy-import insrc/main-v4.js. - Don't bypass
mountShell()to wire your own sidebar/topbar. - Don't
new bootstrap.Modal(...)— there is no Bootstrap. - Don't hard-code
/paths in JS/HTML. - Don't import all of ECharts — match
src/v4/charts.js. - Don't use hex colors in components — use CSS custom properties.
- Don't introduce PostCSS, Tailwind, or any pipeline alongside Vite.
- Don't edit
dist/,node_modules/, ordocs/screenshots/.
Commands
npm run dev # Vite dev server on :9173 (set PORT to override)
npm run build # Production build → dist/
npm run preview # Serve dist/ on :9174
npm run lint # ESLint over src/
npm run lint:fix
npm run format # Prettier write
npm run new -- <slug> # Scaffold a page (use --nav-group, --icon, --title …)
npm run screenshots # Playwright capture (22 pages × light+dark)
npm run smoke # Boot dev server, hit every page, assert 200
npm run analyze # Build + open dist/stats.html
npm run deploy:preview # Build + R2 sync with cache headers
Build under a subpath: BASE_PATH=/foo/ npm run build.
When generating code
- New page → use
npm run new -- <slug> --nav-group "<Group>"rather than crafting the HTML by hand. If you do write by hand, copy the head/body pattern fromproduction/index.html(specifically thedata-shell/data-page/data-breadcrumbtriplet and the<script type="module" src="/src/main-v4.js">tag). - New chart → add a
caseto the switch insideinitCharts()insrc/v4/charts.js. Read tokens viagetComputedStyle(document.documentElement).getPropertyValue('--…'). - New page module → add the lazy-import block at the bottom of
src/main-v4.js, then createsrc/v4/<name>.jsexporting a single idempotentinit<Name>(). - New NAV entry → append to the right group in
NAVinsrc/v4/shell-render.js.{ key, href, text, icon }.keymust match the target page'sdata-page. - New icon → append to
ICONSinsrc/v4/shell-render.js. Inline SVG,currentColorstroke, 24×24 viewbox. - New modal/toast → import
showModal/showToastfromsrc/v4/modal.js/src/v4/toast.js. Don't render backdrops yourself. - New SCSS → add a partial under
src/scss/v4/and@useit frommain.scss. Variables live in_tokens.scss; new tokens get both a light and a dark value.