Introduction
Thank you for purchasing Vireo — we're delighted to have you on board. You've picked up a premium, multi-framework admin & dashboard template built to save you weeks of setup and design work, and this documentation will help you get up and running quickly.
What is Vireo?
Vireo is a complete admin & dashboard starter kit for building back-office apps, analytics panels, SaaS consoles, e-commerce managers, CRMs, and more. Every edition ships with 185+ ready-made pages — dashboards, applications (chat, mail, calendar, file manager, kanban), e-commerce, CRM, projects, crypto, NFT, jobs, blog, authentication, error pages, UI components, forms, tables, charts, maps, and icon sets — all crafted to a single, consistent design standard.
The Aurora design language
Aurora is the visual identity behind Vireo: a refined, modern aesthetic with deep, glassy surfaces and soft glow accents. It's designed dark-first but ships with a fully polished light theme too, so you can match the mood of your product without redesigning a thing. Aurora is powered by a shared design-token core, which means colors, spacing, radii, and typography stay perfectly in sync across components and pages.
One design system, eight editions
Vireo comes in eight standalone editions — HTML, React, Vue, Next.js, Nuxt, Laravel, Django, and PHP. Every edition is a complete, self-contained project that renders the exact same Aurora interface, because they all draw from the same design-token core. The idea is simple: pick the stack you already work in, and you get an identical-looking, identical-featured admin template with no compromise. No need to port a design between frameworks — it's already done.
Feature highlights
- Dark & light themes — Aurora looks stunning in both, switchable at runtime.
- 12 accent presets — recolor the whole UI in a click.
- Live theme customizer — preview themes, accents, layout, and direction instantly.
- Full RTL support — right-to-left layouts are built in, not bolted on.
- 185+ pages per edition — dashboards, apps, e-commerce, CRM, and much more.
- Charts & maps — rich data visualizations and interactive maps out of the box.
- Built on Tailwind CSS v4 — a modern, utility-first styling foundation.
- TypeScript — used across the React, Next.js, Vue, and Nuxt editions.
- Fully responsive — every page adapts cleanly from mobile to widescreen.
- Clean, readable code — organized, consistent, and easy to extend.
New here? Head to Quick Start to get an edition running in about a minute, then explore the per-edition sections for stack-specific details.
Package Contents
When you download Vireo from your account, you'll receive a single ZIP archive. Unzipped, it contains everything you need — all eight framework editions, the documentation, the license, and the changelog:
vireo/
├── Templates/
│ ├── HTML/
│ ├── React/
│ ├── Vue/
│ ├── Next/
│ ├── Nuxt/
│ ├── Laravel/
│ ├── Django/
│ └── PHP/
├── Documentation/
├── LICENSE.txt
└── CHANGELOG.txt
Templates/
The Templates/ folder holds the eight edition sub-folders — HTML, React, Vue, Next (Next.js), Nuxt, Laravel, Django, and PHP. Each one is a complete, standalone project with its own dependencies, build tooling, and README. They all render the same Aurora interface, so choosing an edition is purely a matter of which stack you want to work in.
Every edition includes roughly 185 pages — the full set of dashboards, applications, e-commerce, CRM, projects, crypto, NFT, jobs, blog, authentication, error, UI, forms, tables, charts, maps, and icon pages — so no matter which folder you open, you get the entire template.
You only need one folder. Grab the sub-folder for your stack (for example, Templates/React/) and you can safely ignore the other seven. Nothing is shared between editions at runtime.
Documentation/
The Documentation/ folder contains this guide as a set of HTML pages — open Documentation/index.html in any browser to read it offline. Each edition's README also links back here.
LICENSE.txt
Your license terms for Vireo. Please review it to confirm how you may use the template in your projects.
CHANGELOG.txt
A running log of what changed in each release. Check it after every update so you know exactly what's new and what may need attention in your project.
Requirements
Each Vireo edition is a standalone project, so you only need the tooling for the one you plan to use. The table below lists the runtime each edition depends on. Note that the server-rendered editions (Laravel, Django, and PHP) also use Node.js 18+ to compile their Tailwind CSS v4 asset bundle.
| Edition | Primary requirement | Also needs |
|---|---|---|
| HTML | Node.js 18+ | — |
| React | Node.js 18+ | — |
| Vue | Node.js 18+ | — |
| Next.js | Node.js 18+ | — |
| Nuxt | Node.js 18+ | — |
| Laravel | PHP 8.2+ | Composer, Node.js 18+ (asset build) |
| PHP | PHP 8.2+ | Node.js 18+ (asset build) |
| Django | Python 3.11+ | pip, Node.js 18+ (asset build) |
General tooling
Whichever edition you choose, you'll also want:
- A code editor such as VS Code, WebStorm, or your preferred IDE.
- A terminal to install dependencies and run the dev server.
- A modern browser (recent Chrome, Edge, Firefox, or Safari) to preview the result.
For the Node.js editions, npm ships with Node, so no separate install is needed. You're free to use pnpm or yarn instead if you prefer — just adjust the commands accordingly.
Quick Start
Want to see Vireo running right away? For the Node.js editions (HTML, React, Vue, Next.js, Nuxt) you're about 60 seconds away. The path is always the same: pick your edition folder, open a terminal in it, install, and start the dev server.
- Pick your edition. Inside the unzipped package, open
Templates/and choose the folder for your stack — for exampleReact,Vue, orNext. - Open a terminal in that folder and install dependencies.
- Start the dev server and open the URL it prints.
A typical Node.js edition looks like this (swap React for your chosen edition):
cd Templates/React
npm install
npm run dev
The dev server will print a local URL (usually http://localhost:5173 for the Vite-based editions, or http://localhost:3000 for Next.js and Nuxt). Open it in your browser and you'll see Vireo live, with hot reload as you edit.
The server-rendered editions have a couple of extra steps — Laravel also runs composer install and php artisan serve, Django uses a Python virtual environment plus python manage.py runserver, and PHP builds assets with npm run build then serves via PHP's built-in server. See the section for your edition below for the exact commands.
Every edition folder also ships with its own README.md containing the precise install, run, and build commands for that stack. When in doubt, that README is the fastest reference.
HTML Edition
This is the reference build of Vireo — a static, framework-free version of the entire Aurora dashboard. It is ideal if you want plain, portable HTML/CSS/JS that drops into any stack (or none at all), or if you want a working reference for the styling and interactions before wiring them into your own backend.
Overview
The HTML edition is a fully static, multipage site built with Vite, Tailwind CSS v4, and Alpine.js. Every screen is a real .html file — there is no client-side router and no server runtime. Interactivity (dropdowns, the sidebar, the theme customizer, charts, maps) is handled by Alpine.js and a small set of vanilla scripts. Charts use ApexCharts and maps use Leaflet. Because the final output is nothing more than HTML, CSS, and JS, you can host it on any web server or static host with zero configuration.
A prebuilt static site is already included in the dist/ folder. You can open it or serve it immediately to preview Vireo without installing or building anything.
Prerequisites
You only need Node.js to run the dev server or produce a fresh build. The compiled output itself requires no runtime.
- Node.js 18 or newer (Node 20 LTS recommended).
- npm (bundled with Node.js). You may substitute pnpm or yarn if you prefer.
Installation
From the Templates/HTML folder, install the project dependencies:
cd Templates/HTML
npm install
Development
Start the Vite dev server. It launches on port 5179 with hot module reloading and automatically opens the home page.
npm run dev
Once it is running, the site is available at:
http://localhost:5179/src/html/index.html
Edit any file under src/ and the browser updates instantly.
Production build
Compile the optimized static site into the dist/ folder:
npm run build
This produces a self-contained set of files under dist/: hashed and minified CSS/JS in dist/assets/, and the compiled pages under dist/src/html/ (the home page is dist/src/html/index.html). To review the exact production output locally, use Vite's preview server:
npm run preview
To deploy, upload the entire contents of dist/ to your host and serve dist/ as the web root.
The built pages reference assets with root-absolute paths (for example /assets/vireo-*.css). This means dist/ must be served from the domain root, not from a sub-path such as example.com/vireo/. If you must deploy under a sub-path, set Vite's base option in vite.config.js and rebuild.
- Static host (Netlify, Cloudflare Pages, GitHub Pages, S3/CDN): publish the
dist/folder as the site root. - Node: serve the folder with any static server, for example
npx serve dist. - Vercel: deploy the edition with the output directory set to
distand the build commandnpm run build(no framework preset needed). - PHP / Apache / Nginx: copy the contents of
dist/into your web root (for examplepublic_html) — no PHP is executed, the files are served as-is. - Python host: any static file server works, for example
python -m http.serverrun from insidedist/.
Project structure
Key folders and files in this edition:
| Path | Contents |
|---|---|
src/html/ | Every page as a real .html file, grouped by area (dashboards/, apps/, ecommerce/, crm/, auth/, ui/, forms/, tables/, charts/, maps/, and more). |
src/html/index.html | The entry page (the Sales dashboard). |
src/html/partials/ | Shared Handlebars partials injected at build time: head, header, sidebar, footer, customizer, scripts, loader. These are not built as standalone pages. |
src/styles/ | Tailwind v4 stylesheets — app.css (entry), design tokens/, base.css, components.css, utilities.css, schemes.css (accent presets), plus plugin themes. |
src/js/ | Scripts: vireo.js (main bundle), core/, alpine/ components, pages/ page logic, and chart/map plugins/. |
src/data/ | Static JSON/data used to populate demo tables, charts, and the navigation manifest. |
src/assets/, src/images/, src/icons/, src/illustrations/, src/fonts/ | Static media and font assets. |
vite.config.js | Build configuration: multipage inputs, the Handlebars partial plugin, Tailwind plugin, and dev server (port 5179). |
dist/ | The prebuilt, deployable static site. |
Edition notes
- Routing model. There is no JavaScript router. Each screen is a physical
.htmlfile and links are ordinary<a href>references between them. This keeps the site fully static and SEO-friendly. - Adding a page. Create a new
.htmlfile anywhere undersrc/html/(exceptpartials/). Vite discovers it automatically as a new build input — no configuration needed. Reuse the shared chrome by including partials, e.g.{{> header}}and{{> sidebar}}, and add a link insrc/html/partials/sidebar.htmlso it appears in the navigation. - Partials are build-time. Files in
src/html/partials/are composed into pages by the Handlebars plugin during the build; they are intentionally excluded from the page list and never emitted as standalone pages. - Theming. Light/dark mode and the accent presets are driven by CSS variables and toggled by the built-in customizer; the chosen scheme is persisted in the browser. Accent definitions live in
src/styles/schemes.css. - Root-absolute assets. As noted above, always serve
dist/from the web root. Deploying under a sub-path requires setting Vite'sbaseand rebuilding.
React Edition
The React edition is a single-page application (SPA) build of Vireo using React 19, TypeScript, and Vite, styled with the Aurora design language on Tailwind CSS v4. It ships all 185 template pages as lazy-loaded route components behind a single client-side router, making it the ideal starting point for React developers building a dashboard, admin panel, or internal tool.
Overview
This edition is a fully client-rendered React application. It pairs React 19 and TypeScript with Vite 6 for a fast dev server and an optimized production bundle, uses React Router (react-router-dom v7) for navigation, and renders charts with ApexCharts. Every page is code-split so the initial shell stays small and each screen's code is fetched on demand. It's aimed at teams who want to drop the Vireo UI into a Vite + React project and wire it to their own API.
Prerequisites
- Node.js 18 or newer (which includes npm). Node 20 LTS or later is recommended.
- npm (bundled with Node). Yarn or pnpm work too if you prefer them.
No database, backend service, or environment file is required — the edition runs entirely on demo data included in src/data/.
Installation
From the Templates/React folder, install the dependencies:
cd Templates/React
npm install
Development
Start the Vite dev server with hot module replacement:
npm run dev
Vite prints a local URL — by default http://localhost:5173. Open it in your browser and edits to any file under src/ reload instantly.
Production build
Create an optimized production build:
npm run build
This runs tsc -b (a TypeScript project type-check) and then vite build, emitting a fully static bundle to the dist/ folder — an index.html, hashed JS chunks (one per lazily loaded page), and CSS/asset files. To review the built output locally before deploying, run:
npm run preview
Because the result is static, you can host dist/ on any static file host — Netlify, Vercel, Cloudflare Pages, GitHub Pages, Amazon S3 + CloudFront, or a plain Nginx/Apache server. No Node.js runtime is needed in production.
SPA routing rewrite required. This edition uses HTML5 history routing (BrowserRouter), so a deep link such as /apps/calendar must serve index.html and let the client router resolve the path. Configure your host to rewrite all unmatched routes to /index.html: on Vercel add a catch-all rewrite to /index.html, on Netlify add a _redirects rule /* /index.html 200, and on Nginx use try_files $uri /index.html;. Without this, refreshing a sub-route returns a 404.
Project structure
| Path | What it holds |
|---|---|
index.html | Vite HTML entry; includes the inline anti-flash theme script and the #root mount node. |
src/main.tsx | App entry point — imports the global stylesheet, wires the system-theme listener, and mounts <App />. |
src/App.tsx | Central route map: registers every page slug against its lazy-loaded component and the app shell. |
src/pages/ | All page components, grouped by section (dashboards/, apps/, ecommerce/, ui/, auth/, error/, and more). |
src/components/shell/ | App chrome: Layout, Sidebar, Header, Breadcrumb, Footer, Customizer, CommandPalette. |
src/components/ui/ & charts/ | Reusable UI primitives (Dropdown, Icon) and the ApexChart wrapper. |
src/context/ | React context providers, including CustomizerContext (theme/layout state). |
src/hooks/ | Custom hooks such as useClickOutside and useFocusTrap. |
src/lib/ | Framework-agnostic helpers: theme.ts, color.ts, storage.ts, manifest.ts. |
src/data/ | Demo data and the nav-manifest.json that drives the sidebar navigation. |
src/styles/ | Tailwind v4 + Aurora token stylesheets (app.css is the single entry, plus tokens/, schemes.css, shell.css, and plugin styles). |
public/ | Static assets copied verbatim (e.g. favicon.svg). |
vite.config.ts | Vite config — enables the React and Tailwind v4 plugins. |
tsconfig*.json | TypeScript project references for app and Node/tooling code. |
Edition notes
- Central route map. Routing lives entirely in
src/App.tsx. Two maps drive it:shellfor pages that render inside the sidebar/header layout (as children of<Layout />via an<Outlet />), andstandalonefor full-viewport screens likeauth/*,error/*, and the landing/logout pages that render outside the shell. - Lazy loading. Every page is registered with
React.lazy(() => import(...))and wrapped in a<Suspense>boundary, so each route becomes its own JS chunk and loads on demand. - Home and redirects. The index route
/renders the Sales dashboard, anddashboards/salesredirects to/. Any unknown path renders the 404 screen. - Adding a page. Drop a new component into
src/pages/**, add a matchingconst MyPage = lazy(() => import('./pages/.../MyPage'))declaration, then add one entry to theshellmap (for in-layout pages) or thestandalonemap (for full-screen pages), keyed by its route slug. Add a corresponding item tosrc/data/nav-manifest.jsonif it should appear in the sidebar. - Styling. All styles flow through the single
src/styles/app.cssimport inmain.tsx. Theme, color scheme, and layout options are managed by the Customizer throughCustomizerContextand the helpers insrc/lib/theme.ts. - StrictMode. React StrictMode is intentionally left off so the imperative ApexCharts instances mount once rather than double-rendering in development — keep this in mind if you re-enable it.
Prefer hash-based URLs to avoid server rewrite configuration? You can swap BrowserRouter for HashRouter (both from react-router-dom) in src/App.tsx — links then use /#/route and work on any static host without special routing rules.
Vue Edition
The Vue edition delivers the full Vireo experience as a modern Vue 3 single-page application, written in TypeScript, bundled by Vite, and styled with Tailwind CSS v4. It is aimed at teams building a client-rendered admin panel or dashboard on the Vue ecosystem who want every Aurora screen, the theme customizer, and the router wiring already in place. Navigation runs through Vue Router, every page is a real route, and the same --ax-* design tokens power the shared Aurora look you see across all Vireo editions.
Prerequisites
Before you begin, make sure your machine has the following installed:
- Node.js 18 or newer (Node 20 LTS or later is recommended). This includes
npm, which is used for every command below. - Any modern code editor. For the best experience with
.vuesingle-file components and TypeScript, use VS Code with the official Vue (Volar) extension.
No database, backend runtime, or environment variables are required — this edition is a purely front-end SPA.
Installation
Open a terminal in the Templates/Vue folder and install the project dependencies:
cd Templates/Vue
npm install
This reads package.json and installs Vue 3, Vue Router, Tailwind v4, Vite, ApexCharts, and the TypeScript toolchain into a local node_modules folder.
Development
Start the Vite development server with hot-module replacement:
npm run dev
Vite serves the app at http://localhost:5179 (the port is set in vite.config.ts). The server also binds to your local network, so you can preview on other devices using the network URL Vite prints in the terminal. Edits to any .vue, .ts, or CSS file refresh the browser instantly.
If port 5179 is already in use, change the server.port value in vite.config.ts, or stop the process currently using that port.
Production build
Create an optimized production bundle:
npm run build
This runs vue-tsc -b to type-check the whole project, then vite build to compile and minify everything into a static dist/ folder containing index.html, hashed JavaScript and CSS bundles, and the assets from public/. To preview the built output locally exactly as it will be served in production, run:
npm run preview
Deploying: because the output is fully static, the dist/ folder can be hosted almost anywhere — a static host or CDN (Netlify, Cloudflare Pages, GitHub Pages, Amazon S3), a Node/Nginx server, or any web server capable of serving files. Since this is a client-side SPA using Vue Router with HTML5 history mode, you must add a catch-all rewrite that serves index.html for every unknown path, so deep links such as /dashboards/crm resolve to the app instead of a server 404.
On Vercel, deploying the Vue edition works out of the box: set the build command to npm run build and the output directory to dist — Vercel applies the SPA fallback automatically. For Nginx use try_files $uri $uri/ /index.html;, and for Apache enable a mod_rewrite fallback to index.html.
Project structure
The important files and folders inside Templates/Vue are:
| Path | What it holds |
|---|---|
index.html | The SPA host document. Contains the inline anti-flash theme script that sets the initial Aurora attributes before first paint. |
vite.config.ts | Vite configuration — the Vue and Tailwind v4 plugins, the @ → src path alias, and the dev-server port (5179). |
src/main.ts | Application entry: imports the single stylesheet, boots the theme runtime, and mounts the app with the router. |
src/App.vue | Root component — renders a single <RouterView>; the shell layout is owned by the router. |
src/router/index.ts | The central route registry mapping every URL to a page component (see Edition notes). |
src/layout/AppLayout.vue | The application shell: loader, ambient glow, sidebar, header, footer, customizer, and command palette wrapping the routed page. |
src/pages/ | All page components, grouped into folders (dashboards/, apps/, ecommerce/, auth/, error/, and more). |
src/components/ | Reusable UI: shell/ (sidebar, header, customizer, command palette), charts/, and the AxIcon component. |
src/composables/ | Vue composables such as useTheme, useNav, useDropdown, and useApexChart. |
src/lib/ | Framework-agnostic helpers — the theme engine (theme.ts), storage.ts, color.ts, icons.ts, and the nav manifest.ts. |
src/styles/ | The Tailwind v4 stylesheet layers — app.css is the single entry that pulls in tokens, base, components, shell, and nav styles. |
src/data/ | Demo data and the nav-manifest.json that drives the sidebar menu. |
public/ | Static assets copied verbatim into dist/. |
Edition notes
Routing model. Vireo uses a client-side SPA router. Every screen is a real route defined in src/router/index.ts, which splits routes into two groups:
- Shell pages are children of the
/route, so they render insideAppLayout.vuewith the sidebar, header, breadcrumb, and footer. The empty child path ('') is the default Sales dashboard shown at/. These use lazyimport()so each page is code-split into its own chunk. - Standalone pages — authentication, error/status, and marketing screens like the landing page — are top-level routes that render their own full-page layout and must not be wrapped by the shell.
Adding a page. Create a .vue component under src/pages/, then register it in src/router/index.ts: add it to shellChildren for an in-shell page, or to standaloneRoutes for a full-screen page. Give it a meta.slug so breadcrumbs and the nav manifest resolve correctly. To make it appear in the sidebar, add a matching entry in src/data/nav-manifest.json.
Theming with useTheme. The useTheme() composable (src/composables/useTheme.ts) is a singleton reactive store layered over the lib/theme.ts engine. Components read state (mode, resolved theme, accent, direction, sidebar behavior, layout schemes, and more) and call mutators like toggleTheme(), setMode(), setAccent(), setDir(), and toggleSidebar(). Under the hood these write data-ax-* attributes on <html> and persist choices to localStorage under ax:* keys; a MutationObserver keeps the reactive mirror in sync, so the header toggle, the customizer, and the command palette always agree.
The initial theme is applied by a small inline script in index.html before Vue mounts, which prevents any flash of the wrong theme on first load. Keep that script intact if you customize the host document.
Catch-all placeholders. An in-shell catch-all route renders a PlaceholderPage for any unknown path under the shell, deriving its slug from the URL — handy while you scaffold new sections. Replace it with a real component once the page exists.
Next.js Edition
This edition packages Vireo as a production-ready Next.js 15 application using the App Router, React 19, TypeScript, and Tailwind CSS v4. It is the right starting point if you are building a server-rendered admin dashboard on the Next.js/Vercel stack and want the full Aurora design language, sidebar shell, command palette, and theme customizer wired up out of the box. Every screen is a real, typed React component — ready to connect to your own data and API routes.
Overview
The Next.js edition mirrors the React edition screen-for-screen, but wraps each screen in an App Router route so you get file-based routing, layouts, and the option to fetch data on the server. The app shell (sidebar, header, footer, customizer, command palette, boot loader) is shared across every page through a route-group layout, so adding a page is a matter of dropping in a small route file. It targets teams comfortable with modern React who want a polished, themeable admin foundation rather than a from-scratch build.
Prerequisites
- Node.js 18 or newer — the LTS release (20 or 22) is recommended.
- npm — ships with Node.js. Yarn or pnpm work too if you prefer; the lockfile provided is
package-lock.json. - No database, PHP, or Python runtime is required — this is a pure Node.js front end.
Installation
From the Templates/Next folder, install the dependencies:
cd Templates/Next
npm install
Development
Start the Next.js development server with hot reloading:
npm run dev
Once it is running, open http://localhost:3000 in your browser. The home route renders the Sales dashboard. Edits to any file under app/ or src/ refresh in place.
Production build
Create an optimized production build:
npm run build
npm run start
npm run build compiles the app into the .next/ directory (server bundles, statically prerendered pages, and hashed client assets). npm run start then serves that build as a Node.js server, listening on http://localhost:3000 by default.
Deploying to Vercel: push the Templates/Next folder to a Git repository and import it in Vercel. The framework is detected automatically — no extra configuration is needed, and Vercel runs next build for you.
Deploying on your own Node.js host: run npm run build during release, then keep npm run start alive behind a process manager (for example PM2) or a container. Set the PORT environment variable to change the listening port. Because pages can render on the server, this edition needs a Node.js runtime — it is not a pure static export.
Project structure
| Path | What it holds |
|---|---|
app/layout.tsx | Root layout — document <head>, fonts, global styles, and the theme/customizer provider that wraps the whole app. |
app/(shell)/ | Route group for every page that renders inside the Aurora app shell. Its layout.tsx mounts the sidebar, header, footer, customizer, and command palette. |
app/(bare)/ | Route group for standalone, shell-less screens (auth, error, landing) with their own minimal layout. |
app/(shell)/[...slug]/ | Catch-all route that renders a placeholder for any navigation slug that has no dedicated page yet. |
src/screens/ | The actual screen components, grouped by area (dashboards, ecommerce, forms, tables, and so on). Route files re-export from here. |
src/components/ | Shared building blocks — shell/ (Layout, header, sidebar), ui/, charts/, and icons/. |
src/context/, src/hooks/, src/lib/ | The customizer context, reusable hooks, and helpers for theme, colors, storage, and the navigation manifest. |
src/data/ | Demo data and the nav-manifest.json that drives the sidebar and command palette. |
src/styles/ | The Aurora stylesheet chain — design tokens, base, components, schemes, and plugin styles built on the shared --ax-* token core. |
public/ | Static assets served from the site root (for example favicon.svg). |
next.config.ts · tsconfig.json · postcss.config.mjs | Next.js config, TypeScript config (with the @/* path alias to src/), and the Tailwind v4 PostCSS setup. |
Edition notes
- Routing model. This edition uses the Next.js App Router exclusively. Routes live under
app/; a folder with apage.tsxbecomes a URL. The two route groups —(shell)and(bare)— do not appear in the URL; they only decide which layout wraps a page. - Server vs client components. Route files (the thin
page.tsxre-exports) are Server Components by default. The interactive screens and the app shell begin with the'use client'directive because they use hooks and browser state. Keep that directive at the top of any component that needs interactivity. - Where pages live. Screen components are intentionally kept in
src/screens/, not in apages/folder — a top-levelsrc/pages/would be picked up as the legacy Pages Router. Theapp/route files stay thin and simply re-export the matching screen. - Adding a page. Create the screen in
src/screens/<group>/<Name>.tsx, then add a route file such asapp/(shell)/<area>/<slug>/page.tsxcontaining a one-line re-export, for exampleexport { MyScreen as default } from '../../../../src/screens/<group>/MyScreen';. An explicit route file always wins over the[...slug]catch-all. To add it to the sidebar and command palette, register the slug insrc/data/nav-manifest.json. - Shell-less pages. To render a page without the sidebar/header chrome, place it under
app/(bare)/instead ofapp/(shell)/. - Styling. Tailwind v4 is compiled through the official PostCSS plugin (
postcss.config.mjs) — there is no separate Tailwind config file. The Aurora token chain is imported once via the root layout, so theme, accent, and dark-mode switching work everywhere. - Remote demo images.
next.config.tswhitelistsi.pravatar.cc,picsum.photos, andloremflickr.comfor demo avatars and thumbnails. Swap these for your own asset hosts before going to production.
Nuxt Edition
The Nuxt edition delivers Vireo as a full Nuxt 3 application: Vue 3 with server-side rendering (SSR), TypeScript, and Tailwind CSS v4. It is the right starting point if you want a production-ready Vue dashboard with SSR out of the box, file-based routing, and the option to ship either a Node server or a fully static site.
Overview
This edition wraps the complete Vireo Aurora interface — all dashboards, apps, and eCommerce screens — in an idiomatic Nuxt 3 project. Rendering is server-side by default, pages are wired through Nuxt's file-based router, and the shared --ax-* design tokens are compiled by Tailwind v4 via the official Vite plugin. It suits teams building a Vue-based admin backend who want SSR (or SSG) without assembling the framework, routing, and build tooling themselves.
Prerequisites
- Node.js 18 or newer (Node 20 LTS recommended) — required to install and run Nuxt 3.
- npm (bundled with Node). You may substitute
pnpmoryarnif you prefer; the commands below use npm. - A modern terminal and code editor. No database, PHP, or Python runtime is needed.
Installation
From the Templates/Nuxt folder, install the dependencies. The postinstall hook runs nuxt prepare automatically to generate the typed .nuxt scaffolding.
cd Templates/Nuxt
npm install
Development
Start the Nuxt development server with hot-module reloading:
npm run dev
The app is served at http://localhost:5180 (the port is set to 5180 in nuxt.config.ts). Edits to pages, components, and styles refresh in the browser instantly.
Production build
Vireo Nuxt supports two production targets — pick the one that matches your hosting.
1. SSR / Node server (default). Build a server bundle:
npm run build
npm run preview
This produces a .output/ directory containing a self-contained Nitro server. npm run preview runs it locally so you can verify the production output. To deploy, copy .output/ to your host and start it with node .output/server/index.mjs (it listens on the PORT environment variable).
2. Static site (SSG). Pre-render every route to plain HTML:
npm run generate
This writes a fully static site to .output/public/ that you can upload to any static host — Netlify, Cloudflare Pages, GitHub Pages, S3, or a plain nginx/Apache directory.
On Vercel, no configuration is needed — Nitro auto-detects the platform. Import the repository, set the project root to Templates/Nuxt, and Vercel builds and serves the SSR output automatically. Choose the static route above only if you specifically want a CDN-only, server-less deployment.
Project structure
Application source lives under app/ (configured as srcDir in nuxt.config.ts), while static assets sit at the edition root in public/.
| Path | Contents |
|---|---|
nuxt.config.ts | Nuxt configuration — SSR mode, srcDir, the Tailwind Vite plugin, dev port, and the <head> setup (fonts, favicon, anti-flash theme script). |
app/app.vue | Root component that mounts the layout and router view. |
app/pages/ | File-based routes — each .vue file becomes a URL (e.g. dashboards/, ecommerce/, apps/, auth/). Includes index.vue and a [...slug].vue catch-all. |
app/layouts/ | Shared shells; default.vue renders the sidebar, topbar, and page frame. |
app/components/ | Reusable UI — shell/ (chrome), charts/, auth/, icons, and AxIcon.vue. |
app/composables/ | Vue composables (auto-imported) for shared reactive logic. |
app/lib/ & app/data/ | Helper modules and the demo/sample data used across screens. |
app/styles/app.css | The single global stylesheet — the --ax-* token core compiled by Tailwind v4. |
public/ | Static files served at the site root (e.g. favicon.svg). |
Edition notes
- Routing model. Nuxt uses file-based routing. A file at
app/pages/reports/summary.vueis automatically served at/reports/summary— there is no route table to maintain. - Adding a page. Create a new
.vuefile underapp/pages/, wrap it in the default layout (applied automatically), and add a link in the sidebar component underapp/components/shell/. Then add its entry to the navigation data so it appears in the menu. - Charts and browser-only widgets. ApexCharts and other client-only widgets are wrapped in Nuxt's
<ClientOnly>component so they render only in the browser and never break SSR. When you add your own chart, wrap it the same way to avoid server/client hydration mismatches. - Anti-flash theme. A small inline script runs first in
<head>(configured innuxt.config.ts) to restore the saved theme before first paint, preventing a light/dark flash. Leave it in place when customizing the head. - App sources live in
app/. BecausesrcDirisapp/, the~and@aliases resolve there. Keep new pages, components, and styles insideapp/; static assets belong in the rootpublic/folder.
Laravel Edition
This is the server-rendered edition of Vireo, built on Laravel with Blade templates and Alpine.js for interactivity. Styling is powered by Tailwind CSS v4, and all front-end assets are compiled and served through Vite. It is the right starting point if you want a full PHP application backing your dashboard — real routes, a database layer, and Blade views you can drop dynamic data into — rather than a static export.
Overview
Every page in the template maps to a Blade view under resources/views/pages and is wired up through a single server route in routes/web.php. The Aurora look and feel, the sidebar, header, customizer, and all 186 demo pages are already in place. You get a clean Laravel skeleton with a SQLite database preconfigured, so you can install, migrate, and start building without touching a separate database server.
Prerequisites
Make sure the following are installed and available on your PATH before you begin:
| Tool | Version | Notes |
|---|---|---|
| PHP | 8.3 or newer | Required by the framework; check with php -v. |
| Composer | 2.x | PHP dependency manager, for installing framework packages. |
| Node.js | 18 or newer | Includes npm, used to build the front-end assets. |
The default database is SQLite, so no MySQL or PostgreSQL server is needed to run the template as shipped. A database/database.sqlite file is included and the migration step fills it in.
Installation
From the root of the Laravel edition folder, run the commands below in order. They install the PHP and Node dependencies, create your environment file, generate the application key, set up the database, and build the assets.
composer install
cp .env.example .env
php artisan key:generate
php artisan migrate
npm install
npm run build
On Windows without a Unix-style shell, replace cp .env.example .env with copy .env.example .env.
Development
During development you run two processes side by side: the Vite dev server (which serves and hot-reloads your CSS and JavaScript) and the PHP application server. Open two terminals in the project root.
In the first terminal, start Vite:
npm run dev
In the second terminal, start Laravel:
php artisan serve
Then open the URL printed by php artisan serve — by default http://127.0.0.1:8000. Edits to Blade views, Tailwind classes, and JavaScript are reflected live thanks to Vite's hot-reload.
Keep npm run dev running while you work. If Vite is not running and the assets have not been built, the page cannot resolve its styles and scripts.
Production build
To compile and version the front-end assets for production, run:
npm run build
This writes the optimized, fingerprinted CSS and JavaScript into public/build along with a manifest.json that Blade's @vite directive reads to link the correct hashed files. After building, you no longer need the Vite dev server — Laravel serves the compiled assets directly.
For deployment, this is a standard Laravel application:
- PHP host / VPS: Point your web server (Nginx or Apache) document root at the
public/directory. Runcomposer install --no-dev --optimize-autoloaderandnpm run buildon the server (or upload the builtpublic/buildfolder), set your production values in.env, and ensurestorageandbootstrap/cacheare writable. - Quick preview: After
npm run buildyou can serve locally withphp artisan serveto confirm the production assets load correctly.
Never expose the project root as your web root. Only the public/ folder should be publicly reachable — everything above it (including .env) must stay private.
Project structure
The key folders and files specific to this edition:
| Path | Contents |
|---|---|
routes/web.php | One route per page (186 total). Each maps a URL to a Blade view and passes a title and route slug. |
resources/views/pages/ | All page templates, grouped into folders such as dashboards/, apps/, auth/, charts/, crm/, and ecommerce/. |
resources/views/layouts/app.blade.php | The master layout every page extends (page shell, sidebar, header). |
resources/views/partials/ | Shared fragments: head, header, sidebar, footer, customizer, loader. The @vite asset link lives in head.blade.php. |
resources/css/ | Tailwind entry (app.css) and the Vireo style layers. |
resources/js/ | The Alpine/Vireo bundle (app.js) plus per-page scripts under pages/ for charts and maps. |
vite.config.js | Vite + Tailwind + Laravel plugin config listing every JS/CSS entry point. |
database/ | SQLite file, migrations, factories, and seeders. |
public/ | Web root; public/build holds the compiled, versioned assets. |
.env | Environment configuration (created from .env.example during install). |
Edition notes
- Routing model: Vireo uses one explicit
Route::get()per page inroutes/web.php. Each route returns a Blade view and passes two values —title(used for the browser tab) androute(the slug that drives the active sidebar item and breadcrumb). The/route is the Sales dashboard. - Adding a page: Create a new
.blade.phpfile underresources/views/pages/(extendinglayouts.app), then register a route for it inroutes/web.php, passing a matchingtitleandrouteslug so the navigation highlights correctly. - Assets: The layout links styles and scripts via
@vite(['resources/css/app.css', 'resources/js/app.js']). Add new global JavaScript entries tovite.config.jsif you introduce page-specific bundles. - Database: The template ships with SQLite for zero-config startup. To use MySQL or PostgreSQL instead, update the
DB_*values in.envand re-runphp artisan migrate. - Interactivity: UI behavior (dropdowns, offcanvas, tabs, the theme customizer) is driven by Alpine.js, so most components work declaratively in markup with no extra wiring.
Django Edition
This is the Django 5 build of Vireo: a classic server-rendered admin template where Django owns routing and HTML templates, Tailwind CSS v4 supplies the Aurora styling, and Alpine.js drives the interactive components. Front-end assets are compiled once with Vite and served as static files, so you get a familiar Django project you can drop straight into an existing app or use as the foundation for a new one. It suits teams building Python back ends who want a polished admin UI without adopting a separate JavaScript framework.
Prerequisites
Make sure the following are installed and on your PATH before you begin:
- Python 3.11 or newer — runs Django and the
manage.pycommands. - pip and the
venvmodule — for creating an isolated environment and installing the Python dependencies. - Node.js 18 or newer (bundled with npm) — used only to compile the Tailwind/Alpine assets with Vite.
Node.js is a build-time requirement only. Once npm run build has produced the compiled assets, the running Django site needs Python alone.
Installation
From the Templates/Django folder, create a virtual environment, install both the Python and Node dependencies, compile the assets, and set up the database:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
npm install
npm run build
python manage.py migrate
On Windows, activate the virtual environment with .venv\Scripts\activate instead of the source command above.
Development
Start Django's development server:
python manage.py runserver
The site is served at http://127.0.0.1:8000/, where the root route (/) renders the Sales dashboard.
When you are editing the Tailwind styles or JavaScript, run Vite in watch mode in a second terminal so the compiled assets rebuild automatically as you save:
npm run dev
Vite compiles the source in assets/ into static/dist/. Django (via WhiteNoise) serves those files directly, so you do not need a separate Vite dev server — just keep the watcher running and refresh the browser.
Production build
Compile the optimized assets and gather every static file into a single directory ready to serve:
npm run build
python manage.py collectstatic --noinput
npm run build writes the minified bundle to static/dist/ — vireo.css, vireo.js, the Leaflet map page module, and a manifest.json so templates can link stable URLs. collectstatic then copies static/ and static_src/ (the shared nav manifest, demo data, and favicon) into the staticfiles/ directory defined by STATIC_ROOT.
Because this edition ships with WhiteNoise configured, the collected static files are served—compressed and far-future cached—straight from the Django process, with no separate web server or CDN required. Run it in production with any WSGI/ASGI server, for example Gunicorn:
pip install gunicorn
gunicorn config.wsgi
This is a Python host (not a static, Node, Vercel, or PHP deployment). Before going live, edit config/settings.py: set DEBUG = False, replace the development SECRET_KEY with a secret value, and add your domain to ALLOWED_HOSTS. Deploy behind a platform that runs Python WSGI/ASGI apps (for example Render, Railway, Fly.io, a VPS, or any host with Gunicorn/Uvicorn).
Project structure
| Path | What it holds |
|---|---|
manage.py | Django's command-line entry point (runserver, migrate, collectstatic). |
config/ | Project package: settings.py, urls.py (URL routing), and the wsgi.py / asgi.py servers. |
dashboard/ | The application: views.py (the generic page renderer) plus its templates/ and migrations/. |
dashboard/templates/base.html | The shared shell (sidebar, header, footer, customizer, loader) every page extends. |
dashboard/templates/pages/ | One HTML template per page, grouped by section (dashboards, apps, ecommerce, crm, charts, and so on). |
dashboard/templates/partials/ | Reusable shell fragments included by base.html. |
assets/ | Front-end source: js/app.js entry, the Vireo runtime, Alpine/ApexCharts/Leaflet, and the Tailwind styles/. |
static/dist/ | Vite build output (vireo.css, vireo.js, manifest) — regenerated by npm run build. |
static_src/ | Shared static data served as-is: the nav manifest, demo JSON, and favicon.svg. |
vite.config.js | Vite + Tailwind build config (entry points and output naming). |
requirements.txt | Python dependencies (Django 5, WhiteNoise). |
package.json | Node dependencies and the dev / build asset scripts. |
Edition notes
- Routing model. A single catch-all pattern in
config/urls.pymaps any/section/page/URL todashboard/templates/pages/section/page.htmlthrough the genericrender_pageview. The root/resolves to the Sales dashboard (dashboards/sales). Requesting a URL with no matching template returns a 404. - Adding a page. Create a template at
dashboard/templates/pages/<section>/<name>.htmlthat opens with{% extends 'base.html' %}to inherit the shell, then reach it at/<section>/<name>/— the catch-all route wires it automatically, nourls.pyedit needed. To give it a custom browser title, add its slug to thePAGE_TITLESmap inconfig/urls.py; otherwise the title is derived from the slug. - Active nav & breadcrumb. The view sets an
ax_routeequal to the page slug, which the runtime reads from<html data-ax-route>to highlight the correct sidebar item and build the breadcrumb. Keep new template slugs aligned with the entries in the shared nav manifest so navigation stays in sync. - Rebuild assets after style/JS edits. Changes under
assets/only appear afternpm run build(or whilenpm run devis watching). Editing a Django template alone does not require a rebuild. - Database. The project ships with SQLite for zero-config local runs. Point
DATABASESinconfig/settings.pyat PostgreSQL or MySQL for production.
PHP Edition
The PHP edition delivers the full Vireo admin experience as plain, server-rendered PHP pages — no framework, no build step for the markup. It is aimed at developers who want to drop Vireo into a classic PHP hosting environment (Apache, Nginx + PHP-FPM, or the built-in PHP server) and wire it up to their own backend, database, or CMS. The interface uses PHP include-based partials for the shell (sidebar, header, customizer), Tailwind CSS v4 for styling, and Alpine.js for interactivity. Vite is used only to compile the shared CSS/JS asset bundle; PHP renders every page.
Prerequisites
Make sure the following are installed before you begin:
- PHP 8.2 or newer — required to run the pages and the built-in development server.
- Node.js 18 or newer (with npm) — required only to compile the CSS/JS asset bundle with Vite.
Node.js is a build-time dependency. Once the assets in public/assets/ are compiled, the site runs on PHP alone — Node is not needed on your production server.
Installation
From the Templates/PHP directory, install the build tooling:
npm install
Development
This edition has no separate hot-reload dev server — you compile the assets, then serve the pages with PHP's built-in web server. The quickest way is the combined start script, which builds the assets and then launches the server:
npm run start
Then open http://localhost:8000 in your browser. The root route renders the Sales dashboard.
While iterating on styles or scripts under src/, run the asset watcher in one terminal and the PHP server in another so the bundle rebuilds on every change:
npm run dev
npm run serve
Here npm run dev runs vite build --watch (recompiling public/assets/app.css and public/assets/app.js as you edit), and npm run serve starts php -S localhost:8000 -t public router.php. Refresh the browser to pick up rebuilt assets.
Production build
Compile the optimized CSS/JS asset bundle into public/assets/:
npm run build
This emits two stable, un-hashed files that the PHP templates reference directly: public/assets/app.css (the Tailwind v4 token core and component styles) and public/assets/app.js (Alpine.js, ApexCharts, Leaflet, and the Vireo runtime). Everything the browser loads then lives under public/, which is your document root.
To deploy, upload the entire edition and point your web server's document root at the public/ folder:
- PHP server (Apache / Nginx + PHP-FPM): set the virtual host document root to
public/. All page files (for examplepublic/dashboards/analytics.php) resolve directly from their URL path. Configure your server to serveerror/404.phpfor unknown routes so mistyped URLs return a real 404 rather than falling back to the dashboard. - Local / quick host: run
php -S localhost:8000 -t public router.php(this is thenpm run servescript). The includedrouter.phpserves real files verbatim and returns the 404 page for unknown paths. - Static host / Node host / Vercel / Python host: not applicable — this edition requires a PHP runtime because pages are rendered by PHP at request time. If you need a purely static deployment, use the HTML edition; for a Node, Vercel, or Python target, use the React/Next, Vue/Nuxt, or Django edition instead.
The compiled public/assets/ folder is intentionally git-ignored — treat it as a build artifact and regenerate it with npm run build rather than committing it.
Project structure
| Path | What it holds |
|---|---|
public/ | The document root. Contains every page as a .php file, organized into folders (dashboards/, apps/, ui/, forms/, tables/, charts/, auth/, error/, and more), plus index.php (the Sales dashboard), favicon.svg, the built assets/ bundle, and the static data/ demo files. |
partials/ | Shared shell includes: config.php (bootstrap and helper functions), head.php, header.php, sidebar.php, footer.php, scripts.php, loader.php, and customizer.php. |
router.php | Front controller for the built-in PHP server — resolves URLs to real files, guards against path traversal, and returns the 404 page for unknown routes. |
src/ | Asset sources compiled by Vite: src/styles/ (Tailwind v4 layers, design tokens, component and utility CSS) and src/js/ (Alpine setup, core UI logic, page scripts, and plugins). src/main.js is the single build entry. |
vite.config.js | Vite configuration that compiles src/main.js into the stable app.css / app.js pair under public/assets/. |
package.json | npm scripts (build, dev, serve, start) and the build/runtime dependencies. |
Edition notes
Routing is filesystem-based. There is no route table — a page exists the moment its .php file exists under public/. The URL mirrors the file path: public/dashboards/analytics.php is served at /dashboards/analytics.php, and public/index.php is the root route.
How a page is composed. Every page declares its title and manifest route, includes the shared bootstrap, then assembles the shell from partials. Each page begins like this:
<?php
$ax_title = 'Sales';
$ax_route = 'dashboards/sales';
require __DIR__ . '/../partials/config.php';
?>
The config.php bootstrap exposes three helpers used throughout the templates: ax_partial('sidebar') renders a shell partial by name, ax_asset('app.css') returns the absolute web path to a built asset, and ax_url('dashboards/sales') builds an absolute page URL from a slug.
Adding a new page. Copy an existing page (for example public/index.php or any file under public/dashboards/) to your new path under public/, update $ax_title and $ax_route at the top, and adjust the depth of the require to partials/config.php so it points to the edition root — pages at the web root use __DIR__ . '/../partials/config.php', while a page one folder deeper (such as public/apps/foo/bar.php) needs an extra ../. Then write your page markup between the shell partials.
The require path to partials/config.php is relative to the page's folder depth. If a new page renders unstyled or throws an include error, the number of ../ segments is almost always the cause — count the folders between the page and the public/ root.
The data/ folder holds static JSON used by the demo (navigation manifest and sample datasets). It is served statically alongside the pages and can be replaced with output from your own backend.
Project Structure
Vireo ships in eight editions — a plain HTML reference plus React, Vue, Next.js, Nuxt, Laravel, Django and PHP. Every edition is built on the same Aurora foundations: an identical design-token core, one navigation data file, and a set of framework-agnostic core modules. Because these pieces are copied verbatim into each stack, theming and behaviour are pixel-for-pixel consistent everywhere.
The shared pillars
| Location | What it holds | Role |
|---|---|---|
src/styles/tokens/ | _primitives.css (raw scales), _roles.css (semantic aliases), _accents.css (12 presets), _charts.css, _recipes.css | The --ax-* token core — the single source of truth for colour, radius, type and shadow. |
src/styles/app.css | The one stylesheet entry: imports Tailwind v4, the token chain, then base/components/nav/shell/utilities | Defines the import order and the Tailwind @theme bridge that exposes tokens as utilities. |
src/data/nav-manifest.json | One ordered list of navigation nodes | The single source of truth for all navigation surfaces. |
src/js/core/ | theme-restore.js, customizer.js, color.js, sidebar.js, command-palette.js, nav.js, manifest.js, storage.js | The behavioural core: theming, the customizer, the sidebar, and the command palette. |
src/html/ (and each edition's component/template tree) | Page markup and reusable partials (head, header, sidebar, customizer, footer) | Where per-page content lives; the shell chrome is shared through partials/components. |
The core modules at a glance
- Theme —
theme-restore.jsre-derives everydata-ax-*attribute on<html>from storage and keeps the canvas in sync with the OS theme. - Customizer —
customizer.jsis the logic layer behind the settings drawer (theme, accent, direction, layout), writing attributes and persisting choices.color.jsderives a full accent ramp from any custom hex. - Sidebar —
sidebar.jsrenders and manages the collapsible navigation rail. - Command palette —
command-palette.jspowers the searchable quick-jump overlay. - Manifest loader —
manifest.jsfetchesnav-manifest.jsononce and shares a single indexed tree (by id, by slug, with parent/child trails) across every navigation surface.
One navigation file, three surfaces
The sidebar, the breadcrumb trail, the sidebar filter and the command palette are all driven by nav-manifest.json. Each node carries a stable shape — id, title, slug, icon (a Tabler icon name), parent, section, order, badge and search keywords.
Add, rename, reorder or re-icon a page by editing one entry in nav-manifest.json, and the sidebar, breadcrumbs and command palette update together — no need to touch markup in three places. This applies to the editions that render navigation from the manifest.
Theming & Design Tokens
Vireo is themed entirely through CSS custom properties — the --ax-* design tokens — combined with data-ax-* attributes on the root <html> element. Components never hard-code colours or radii; they read tokens. Change a token once and every component that consumes it updates, in both light and dark mode.
How the tokens are layered
The token core lives in src/styles/tokens/ and is built in three layers:
- Primitives (
_primitives.css) — the raw scales: neutral/dark colour ramps, the accent ramp, radii, fonts and shadows. - Roles (
_roles.css) — semantic aliases that components actually use, such as--ax-canvas,--ax-surface,--ax-textand--ax-accent. Light values sit on:root; dark values are defined under[data-ax-theme="dark"]. - Accents (
_accents.css) — the 12 preset accent palettes, each keyed by a[data-ax-accent="…"]block.
A handful of the most-used role tokens:
| Token | Purpose |
|---|---|
--ax-canvas | Page background (the app canvas). |
--ax-surface / --ax-surface-raised | Glass card and header/sidebar surfaces. |
--ax-text-strong / --ax-text / --ax-text-muted | Heading, body and secondary text ink. |
--ax-border / --ax-border-strong | Hairline and stronger strokes. |
--ax-accent / --ax-accent-hover / --ax-on-accent | Brand accent, its hover state and the ink that sits on top of it. |
--ax-radius-xl / --ax-radius-pill | Aurora's high card radius and full pill radius. |
--ax-font-sans / --ax-font-display | Body font (Inter) and display font (Space Grotesk). |
Changing the look
To retune the whole interface, override the role or primitive tokens in your own stylesheet (loaded after app.css). For example, to soften the corner radius and warm up the surfaces:
:root {
/* dial the Aurora radius down for a squarer look */
--ax-radius-xl: 16px; /* cards */
--ax-radius-md: 10px; /* buttons, inputs */
/* nudge the light canvas + card surface */
--ax-canvas: #F5F3EF;
--ax-surface: #FFFFFF;
}
[data-ax-theme="dark"] {
/* dark-mode overrides live in their own block */
--ax-canvas: #0B0D12;
--ax-text: #D4DAE4;
}
Because tokens flow through the Tailwind v4 @theme bridge in app.css, these same variables also back utilities like bg-surface, text-strong and rounded-xl — so a token change is reflected in the utilities too.
All eight editions copy the identical token core. A change you make to a --ax-* token can be dropped into any other stack unchanged and produces the exact same result — theming ports across React, Vue, Next, Nuxt, Laravel, Django, PHP and the HTML reference without translation.
Prefer overriding the role tokens (--ax-surface, --ax-text, --ax-accent…) over the raw primitive ramps. Roles are the documented contract components read; primitives may shift between releases.
Dark Mode & Accent Colors
Vireo ships a fully realised light and dark theme plus twelve accent palettes, all switchable at runtime from the customizer drawer and persisted per visitor. Everything is driven by two attributes on <html>: data-ax-theme for the mode and data-ax-accent for the accent.
Light, dark & system
The mode has three settings, stored under the ax:theme key:
- light —
data-ax-theme="light" - dark —
data-ax-theme="dark" - system — follows the operating system via the
prefers-color-schememedia query, and keeps tracking it live (no reload) as long as the visitor stays on "system".
The default is system. Light values are defined on :root and dark values under [data-ax-theme="dark"], so the resolved mode simply picks which token block wins. The header also carries a quick toggle that flips light and dark directly.
The twelve accent presets
An accent is a full colour ramp plus its role aliases. Vireo includes 12 presets:
Verdigris (the default), Cobalt, Indigo, Amethyst, Magenta, Terracotta, Amber, Olive, Forest, Teal, Slate and Graphite.
Selecting one writes data-ax-accent="cobalt" (and so on) and stores it under ax:accent. Verdigris is special: as the default it needs no attribute, so choosing it simply removes data-ax-accent. Each preset defines a light block and a dark compound block, so accents stay legible in both modes automatically.
A custom accent
Beyond the presets, the customizer accepts any hex colour. Vireo derives a complete 50→900 ramp from your colour, picks a contrast-correct ink for --ax-on-accent, sets data-ax-accent="custom", and saves the chosen hex under ax:accent-custom. You can also set a custom canvas background per mode (saved under ax:bg-custom and ax:bg-custom-dark).
The anti-flash script
To guarantee zero flash of the wrong theme, a tiny synchronous script runs first inside the document <head>, before any stylesheet. It reads the stored ax:* preferences, resolves "system" against prefers-color-scheme, and writes data-ax-theme, data-ax-accent, dir and lang onto <html> before the first paint.
This inline script must remain the very first executable element in <head>, ahead of the stylesheet link. Moving it after the CSS, or removing it, reintroduces a visible theme flash on load. It is intentionally framework-agnostic and wrapped in try/catch so storage can never block rendering.
How defaults are chosen & persisted
Every customizer choice is written to localStorage under the ax: prefix — for example ax:theme, ax:accent, ax:accent-custom and ax:lang. On the next visit the anti-flash script restores them instantly. If nothing is stored, Vireo falls back to its shipped defaults: system theme and the Verdigris accent. A schema guard (ax:schema) safely clears stale keys if the storage shape ever changes, and the customizer's Reset returns every setting to these defaults.
To ship a different out-of-the-box look, change the defaults the restore logic falls back to (for instance default to dark and the cobalt accent). Because the inline head script and the theme-restore module resolve identically, update both so first paint and re-sync agree.
RTL & Languages
Vireo has first-class right-to-left support. The entire interface is built on CSS logical properties, so switching direction mirrors layout, spacing, icons and navigation without any per-page changes.
Turning on RTL
Direction is controlled by two attributes on <html>: the standard dir attribute (ltr or rtl) and, for persistence, the ax:dir storage key. Toggling RTL in the customizer sets dir="rtl" and stores ax:dir="rtl"; switching back to LTR sets dir="ltr" and clears the key so the default returns.
Forcing RTL as the default
To make right-to-left the shipped default for every visitor, set the direction before first paint. The simplest, flash-free approach is to hard-code it on the root element in your page template:
<html lang="ar" dir="rtl">
Alternatively, seed the persisted preference so the anti-flash script restores it on every load:
localStorage.setItem('ax:dir', 'rtl');
An explicit ax:dir value always wins. If it is not set, direction is inferred from the language — Arabic (AR) resolves to RTL, every other language to LTR.
The header language toggle
The header includes a language menu (the EN button, top-right) offering English, Español, Français, العربية, Deutsch, 中文, Italiano and Русский. Picking a language updates the visible code, writes ax:lang, and sets the lang attribute on <html>.
Selecting Arabic automatically switches the app into RTL the first time it is chosen — unless the visitor has already set a direction explicitly, in which case their choice is respected. Direction and language are otherwise independent, so you can pair any language with either direction from the customizer.
The language menu drives layout direction and locale codes; it is not a bundled translation system. Wire the ax:lang value into your own i18n library to swap the actual UI strings, while Vireo handles the RTL mirroring for you.
Live Customizer
Vireo ships with a live Theme Customizer — a slide-in panel that lets you (and, if you leave it enabled, your end users) reshape the entire shell in real time. Every change is applied to the page instantly and saved to the browser, so the look you pick sticks on the next visit.
Opening the panel
The launcher is the gear (cog) button in the top header, next to the other header actions. Clicking it dispatches the ax-customizer-open event, which slides the panel in from the edge of the screen. The panel is titled Theme Customizer and carries the note “Live preview — changes save automatically.” Press Escape or click the backdrop to close it.
Under the hood every control writes a data-ax-* attribute onto the <html> element and mirrors it to a matching ax:* key in localStorage. Choosing a control’s default value removes both the attribute and the stored key, keeping the DOM and storage clean.
Changes are throttled and non-destructive — charts, code blocks and other themed widgets re-theme themselves live via an internal ax:change event, so you never need to reload to preview a setting.
Controls
The following table documents every control the panel exposes, top to bottom.
| Control | What it does | Values |
|---|---|---|
| Color Mode | Switches the interface between the light and dark palettes. System follows the operating-system preference live (via prefers-color-scheme) and tracks it without a reload. |
light · dark · system (default system) |
| Direction | Sets the document reading direction for full right-to-left support. Flips the dir attribute on <html>. |
LTR · RTL (default LTR) |
| Accent Presets | Picks the brand accent color from twelve curated presets. Each preset regenerates the full accent ramp and chart colors. | Verdigris (default) · Cobalt · Indigo · Amethyst · Magenta · Terracotta · Amber · Olive · Forest · Teal · Slate · Graphite |
| Custom Colors — Primary | A color picker plus hex field for a bespoke accent. Vireo derives a complete tint/shade ramp and an accessible on-accent text color from your single hex. Recently used colors are remembered as quick swatches. | Any #RRGGBB hex |
| Custom Colors — Background | Overrides the page canvas color, stored per mode (a light-mode background never bleeds into dark). Four one-click tints are provided, and a low-contrast warning appears if the chosen color would hurt readability. | Any #RRGGBB hex · presets: Porcelain, Cool Gray, Warm Sand, Slate Mist |
| Navigation — Orientation | Chooses the primary navigation layout: a vertical sidebar, a horizontal top menu, or a hybrid of both. | vertical (default) · horizontal · hybrid |
| Navigation — Menu interaction | How submenus open. Hover opens the top bar and the collapsed sidebar’s flyouts on pointer-over; the expanded sidebar always opens submenus on click. | click (default) · hover |
| Shell Style | Governs the sidebar and header together. Docked keeps them flush to the edges; Detached floats both as inset cards. Hidden when navigation is Horizontal (no rail to dock). | default (Docked, default) · detached |
| Sidebar — Behavior | Controls the rail. Collapsible keeps the header collapse toggle; Expanded locks the full rail open; Compact locks the icon-only rail with fly-out submenus. Hidden when navigation is Horizontal. | collapsible (default) · expanded · compact |
| Sidebar — Position | Whether the sidebar stays pinned while the page scrolls, or scrolls away with the content. | fixed (default) · static |
| Sidebar — Color scheme | The sidebar’s surface treatment, independent of the overall light/dark mode. | light (default) · dark · brand · gradient · transparent |
| Sidebar — Background image | Applies a subtle texture behind the sidebar. Renders over the Light sidebar scheme only. | none (default) · texture-1 … texture-6 |
| Header — Position | Whether the top header stays pinned or scrolls away with the page. | fixed (default) · static |
| Header — Color scheme | The header’s surface treatment, independent of the overall light/dark mode. | light (default) · dark · brand · gradient · transparent |
| Layout — Page style | Adjusts content-area density and card framing. | regular (default) · classic · compact |
| Layout — Width | Whether the content area stretches edge to edge or fills the full viewport width. | fluid (default) · full |
| Misc — Page loader | Toggles the animated page-load overlay shown during navigation. | on (default) · off |
The header’s sidebar collapse toggle is remembered separately from the panel (as ax:collapsed). It only takes effect in the Collapsible behavior — the Expanded and Compact behaviors lock the rail and ignore it.
Reset and Copy config
The panel footer has two actions:
- Reset — clears every
ax:*key, removes alldata-ax-*attributes and any inline custom-color styles, and returns the shell to its shipped defaults. (The panel keeps a one-step snapshot so a reset can be undone.) - Copy config — snapshots your current settings and copies them to the clipboard (showing a “Config copied” toast). This is the exact set of values you would bake in to make your look the default for everyone — see Making a configuration the default.
Making a Configuration the Default
The customizer is per-visitor: every choice is stored in the browser under the ax: namespace, so a returning user sees exactly what they last picked. When you want a specific look to be the out-of-the-box default for everyone — before they touch a single control — you bake it into the template. This page explains how persistence works and how to set your own defaults.
How settings persist
Two things happen on every change. The value is written as a data-ax-* attribute on the <html> element (which the CSS reads), and it is mirrored to a matching ax:* key in localStorage. The key/attribute pairs are:
| Setting | localStorage key | <html> attribute | Default |
|---|---|---|---|
| Color mode | ax:theme | data-ax-theme (resolved light/dark) | system |
| Direction | ax:dir | dir | ltr |
| Accent preset | ax:accent | data-ax-accent | verdigris |
| Custom accent hex | ax:accent-custom | inline CSS vars + data-ax-accent="custom" | — |
| Custom background (light / dark) | ax:bg-custom / ax:bg-custom-dark | inline --ax-canvas | — |
| Navigation orientation | ax:nav | data-ax-nav | vertical |
| Menu interaction | ax:menu | data-ax-menu | click |
| Shell style | ax:shell-style | data-ax-shell-style | default |
| Sidebar behavior | ax:sidebar-behavior | data-ax-sidebar-behavior | collapsible |
| Sidebar position | ax:sidebar-position | data-ax-sidebar-position | fixed |
| Sidebar color scheme | ax:sidebar-scheme | data-ax-sidebar | light |
| Sidebar background image | ax:sidebar-image | data-ax-sidebar-image | none |
| Header position | ax:header-position | data-ax-header-position | fixed |
| Header color scheme | ax:header-scheme | data-ax-header | light |
| Page style | ax:page | data-ax-page | regular |
| Layout width | ax:width | data-ax-width | fluid |
| Page loader | ax:loader | data-ax-loader | on |
| Sidebar collapse toggle | ax:collapsed | data-ax-collapsed | expanded |
To keep the DOM tidy, a value that equals its default is not written — the attribute and key are removed instead. A tiny anti-flash script at the very top of <head> re-reads these keys on every load and writes the attributes back onto <html> before the first paint, so there is never a flash of the wrong theme.
Start from “Copy config”
Design your ideal shell in the live customizer, then click Copy config in the panel footer. That copies a JSON snapshot of your non-default settings to the clipboard — the exact list of values to bake in. For example:
{
"theme": "dark",
"accent": "cobalt",
"nav": "horizontal",
"sidebar-scheme": "dark",
"width": "full"
}
Each key is simply the ax: key with the prefix dropped, so "accent": "cobalt" corresponds to data-ax-accent="cobalt", and so on using the table above.
Baking the default into the template
The single source of truth for defaults is the anti-flash script at the top of the document head (in the HTML edition, src/html/partials/head.html; every other edition has the identical script in its document head). Because that script strips any attribute whose stored value is missing or equal to the default, hardcoding data-ax-* on the <html> tag alone will not survive — you change the defaults inside the script instead. Edit the fallbacks and the setAttr(attribute, key, default) calls so an absent key resolves to your chosen value:
// Color mode — was 'system'
var theme = get('ax:theme') || 'dark';
// Accent — was 'verdigris'
var accent = get('ax:accent') || 'cobalt';
// (also update the guard below so the default accent still writes its attribute)
if (accent === 'cobalt') D.removeAttribute('data-ax-accent');
else D.setAttribute('data-ax-accent', accent);
// Layout / scheme attributes — change the 3rd argument (the default)
setAttr('data-ax-nav', 'ax:nav', 'horizontal');
setAttr('data-ax-sidebar', 'ax:sidebar-scheme', 'dark');
setAttr('data-ax-width', 'ax:width', 'full');
Keep the defaults in sync across three files so the customizer’s Reset and its “is this the default?” detection agree with what visitors actually see: the anti-flash script in the head, the ATTR_KEYS list in src/js/core/theme-restore.js, and the REGISTRY object in src/js/core/customizer.js. All three carry the same attribute / key / default triples.
Forcing a new default onto returning visitors
A visitor who has already used the customizer has their own ax:* keys, and those always win over the baked defaults. If you change the shipped look and want everyone pushed onto it — including people who customized under an older version — bump the schema version. The stored value ax:schema is compared against the constant SCHEMA (currently '1') in src/js/core/storage.js and mirrored in the head script; when they differ, all ax:* keys are wiped on the visitor’s next load, dropping them back onto your new defaults.
// src/js/core/storage.js
export const SCHEMA = '2'; // bump to invalidate previously stored settings
Increment the same version number in the head script’s schema-guard check so the pre-paint pass and the module agree. New visitors with no stored settings simply pick up your baked defaults immediately — no schema bump needed.
Adding & Editing Pages
Every edition of Vireo shares the same page anatomy: a shell (sidebar + header + footer) wraps a <main> region that holds your content. The sidebar, breadcrumbs, sidebar filter and command palette are all driven by a single ordered data source — nav-manifest.json — so a page is fully wired only when both the view and its manifest entry exist.
The two things every page needs
- A view/route — the actual markup or component for the page, in the location your stack expects.
- A manifest node — one entry in
nav-manifest.jsonso the page appears in navigation, gets a breadcrumb, and is reachable from the command palette (Ctrl/⌘ + K).
Where each stack keeps its pages
| Edition | Add the view here | Wire the route |
|---|---|---|
| HTML | A new .html file under src/html/ | Auto-discovered by Vite (glob); add a nav-manifest.json entry |
| React | A page component under src/pages/ | Register it in the router, then add a manifest entry |
| Vue | A page component under src/pages/ | Register the route, then add a manifest entry |
| Next | A file in the app/ routes tree | File-system routing; add a manifest entry |
| Nuxt | A file under app/pages/ | File-system routing; add a manifest entry |
| Laravel | A Blade view under resources/views/ | Add a route in routes/web.php, then a manifest entry |
| Django | A template under the app's templates/ | Add a URL pattern in urls.py, then a manifest entry |
| PHP | A file under public/src/ | Reachable by path; add a manifest entry |
In the HTML edition you never edit a build config to register a page. Vite globs src/html/**/*.html (everything except src/html/partials/) at build time, so dropping in a file is enough to make it a real, built page.
Anatomy of an HTML page
Pages are assembled from shared Handlebars partials, so you only write the unique <main> content. The data-ax-route attribute on <html> is what links the page back to its manifest node (for the active nav item, title and breadcrumb):
<!doctype html>
<html lang="en" data-ax-route="reports/summary">
<head>{{> head}}</head>
<body>
{{> loader}}
<div class="ax-layout">
{{> sidebar}}
<div class="ax-shell">
{{> header}}
<main class="ax-main" id="ax-main">
<!-- your page content -->
</main>
{{> footer}}
</div>
</div>
{{> scripts}}
</body>
</html>
Worked example — a new "Summary" report page (HTML)
- Create the file
src/html/reports/summary.htmlusing the anatomy above, settingdata-ax-route="reports/summary". - Open
src/data/nav-manifest.jsonand add a node so it shows in the sidebar. Each node follows the field contract{id, title, slug, icon, parent, section, order, badge, keywords, inMenu, alias}, whereiconis a Tabler icon name andslugmatches the route:
{ "id": "reports.summary", "title": "Summary", "slug": "reports/summary",
"icon": "report", "parent": "grp.reports", "section": null, "order": 1,
"badge": null, "keywords": ["summary","report","overview"],
"inMenu": true, "alias": null }
If the page belongs to a brand-new top-level group, add a group node too (with parent: null, a section, and a slug pointing at its landing leaf), then reference that group id as the parent of your leaf. Run the dev server and the new item appears in the sidebar, breadcrumb and command palette automatically:
npm install
npm run dev
To edit an existing page, change its <main> content directly; to rename or reorder it in the menu, edit the matching node's title, order or badge in nav-manifest.json. Shared chrome (topbar, sidebar, footer) lives in src/html/partials/ — edit it once and every page updates.
Charts
Vireo standardizes on a single, best-in-class charting engine: ApexCharts. Every chart in the template — line, area, bar, pie/donut, mixed, financial (candlestick), radial gauges and sparklines, and the demo pages branded as Chart.js and ECharts galleries — is rendered through one shared wrapper. That means there is only one API to learn, and every chart inherits the same theming, animation and accessibility behaviour.
How chart pages are wired
The wrapper lives at src/js/plugins/charts.js and exposes a small, friendly API. There are two ways to create a chart:
1. Declarative (auto-init)
Mark an element with data-ax-chart="apex" and describe it with data-ax-* attributes. On page load, initCharts() scans for these elements and mounts them. Charts below the fold are deferred with an IntersectionObserver so the (lazy-imported) ApexCharts bundle only loads when a chart actually scrolls into view:
<div data-ax-chart="apex"
data-ax-chart-type="area"
data-ax-chart-height="320"
data-ax-chart-series='[{"name":"Revenue","data":[42,48,45,53,57]}]'>
</div>
Series can be supplied inline as JSON in data-ax-chart-series, or referenced by key from a global window.AX_DATA object via data-ax-chart-data.
2. Programmatic
Import renderChart and call it directly — this is how the gallery pages build their richer examples:
import { renderChart } from '/src/js/plugins/charts.js';
renderChart(document.getElementById('my-chart'), 'line', [
{ name: 'Revenue', data: [42, 48, 45, 53, 57, 55, 62] },
{ name: 'Target', data: [45, 48, 50, 52, 55, 57, 60] },
], { height: 320, accent: true, legend: 'none' });
Options include height, sparkline, accent (use the current accent as the first series colour), legend, stacked, tooltip, color, and an apex escape hatch that is deep-merged over the themed base so you can pass any raw ApexCharts option.
Client-side rendering & live theming
Charts initialize on the client, after the shell has laid out. The wrapper reads the resolved design tokens (--ax-chart-1…--ax-chart-6, text, border, surface and font tokens) straight from CSS, so every chart automatically matches the current look. When the user switches light/dark, picks one of the accent presets, or flips to RTL, the app fires an ax:change event and each registered chart re-themes in place within a couple hundred milliseconds — no reload, no re-mount. Charts also respect prefers-reduced-motion by disabling animations, reserve their height up front to avoid layout shift, and re-fit on container resize.
Because colours are read from CSS tokens rather than hard-coded, the cleanest way to recolour a chart globally is to change the palette tokens (or the accent) — every chart follows.
Chart demo pages
Browse the live examples under Charts in the sidebar (files in src/html/charts/):
- Line —
charts/apex-line - Area —
charts/apex-area - Bar & Column —
charts/apex-bar - Pie & Donut —
charts/apex-pie - Mixed / Combo —
charts/apex-mixed - Financial (candlestick) —
charts/apex-financial - Sparklines —
charts/sparklines - Chart.js Gallery —
charts/chartjs(rendered via the ApexCharts wrapper) - ECharts Gallery —
charts/echarts(radial gauges & more, rendered via the ApexCharts wrapper)
Each demo page imports charts.js in a small module script at the bottom and calls renderChart with its own data — copy any block as a starting point for your own charts.
Maps & Icons
Maps
Vireo ships two map pages, and both work out of the box with no API key.
Leaflet (interactive)
The primary map (maps/leaflet, code in src/js/pages/maps-leaflet.js) is a real, fully interactive Leaflet map. It uses free CARTO basemaps (Positron / Dark / Voyager) plus OpenTopoMap terrain tiles, and demonstrates themed markers, popups, a GeoJSON-style region overlay and a density layer. The surrounding UI (layer switches, branch cards) talks to the map through browser CustomEvents, and marker/region colours re-theme on the same ax:change event the rest of the app uses, so pins stay on-brand when you change accent or toggle dark mode. To point it at your own data, edit the BRANCHES array (id, name, lat/lng, accent token) at the top of the page script.
Google Maps (embed)
The maps/google page uses a keyless Google Maps embed (an <iframe> pointed at google.com/maps?…&output=embed) that recenters on the active location and supports map/satellite/terrain modes. Because it is an embed, there is nothing to configure to see it working; if you need programmatic markers, drawing or Street View, swap the iframe for the official Google Maps JavaScript SDK and add your own API key.
Leaflet is bundled as a dependency; the Google page needs no account or key as shipped. Both maps are demonstrations — replace the demo coordinates with your locations.
Icons
Vireo uses the Tabler icon set as its system iconography. Icons are embedded as inline SVG (not an icon font and not a runtime dependency), drawn on a 24×24 grid using currentColor — so an icon inherits the text colour of its container and is sized with CSS. Every icon carries the ax-icon class:
<svg class="ax-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"
width="24" height="24" aria-hidden="true">
<path d="M5 12l5 5l10 -10" /> <!-- "check" -->
</svg>
The four icon libraries
| Page | Route | What it is |
|---|---|---|
| Tabler | icons/tabler | The system set — 5,000+ pixel-perfect glyphs on the 24×24 grid |
| Line | icons/line | A lighter, Feather-style aesthetic — 1.5px hairline outline strokes |
| Solid | icons/solid | Heavier filled glyphs for emphasis (toolbars, active states, chips) |
| Brands | icons/brands | Social, auth-provider and payment marks for sign-in and share rows |
Each icon page is a searchable gallery — type to filter, then click any tile to copy its name.
Using an icon
Find the glyph you want on the icons/tabler page, then paste its SVG markup wherever you need it, keeping the ax-icon class. For a button, wrap it as a ax-btn__icon; for a standalone control, use an ax-icon-btn. Colour follows the surrounding text, so no extra styling is usually needed.
Swapping an icon
Because each icon is just inline SVG, swapping one is a copy-and-replace: keep the outer <svg class="ax-icon" …> element and replace the inner <path> data with the paths from your chosen Tabler glyph. Grab the exact paths from tabler.io/icons (choose the outline variant to match the 1.75px stroke style used throughout).
Keep the viewBox="0 0 24 24", stroke="currentColor" and fill="none" attributes intact when swapping outline icons — they are what make every icon share one weight and tint. For a decorative icon keep aria-hidden="true"; if the icon is the only label for a control, add an aria-label to the control instead.
Plugins & Credits
Vireo is deliberately lightweight. Rather than stacking up dozens of single-purpose libraries, most interactive components — data tables, carousels, rich-text editors, dropzones, date and select pickers, drag-and-drop lists — are built natively with Alpine.js and Tailwind and styled after the popular libraries you know. That keeps the bundle small and the code easy to own. The list below covers the third-party open-source libraries that are actually bundled and running in the template.
Bundled libraries
| Library | Purpose | License |
|---|---|---|
| Alpine.js (with the collapse & focus plugins) | Lightweight reactivity for all interactive UI — menus, tabs, modals, toggles, the customizer and command palette | MIT |
| ApexCharts | Every chart in the template (line, area, bar, pie/donut, mixed, financial, radial gauges, sparklines) | MIT |
| Leaflet | The interactive map page — tiles, markers, popups and overlays | BSD-2-Clause |
| Tailwind CSS v4 | The utility-first styling engine behind the whole design system | MIT |
Build tooling
| Tool | Purpose | License |
|---|---|---|
| Vite | Dev server and production bundler (multi-page build) | MIT |
| vite-plugin-handlebars | Shared header/sidebar/footer partials across HTML pages | MIT |
| Prettier | Code formatting | MIT |
Icons & maps
The interface icons are the Tabler icon set (MIT), embedded as inline SVG. The Google Maps page uses a keyless Google Maps embed; Leaflet basemap tiles are served by CARTO and OpenTopoMap over OpenStreetMap data — please keep their attribution intact when you ship.
Components that look like Grid.js / DataTables, Swiper, Quill, Dropzone, Flatpickr or Choices are re-implemented natively with Alpine.js and CSS, so they add no extra dependencies. If you prefer the original library for a given component, you are free to drop it in.
Fonts
Vireo uses three open-source typefaces, loaded from Google Fonts:
- Inter — the primary UI/body typeface (SIL Open Font License).
- Space Grotesk — display face for headings and KPI figures (SIL Open Font License).
- JetBrains Mono — monospace for numeric axes, code and tabular data (SIL Open Font License).
All three are free for commercial use under the Open Font License. To self-host instead of using the CDN, swap the Google Fonts <link> in src/html/partials/head.html for local @font-face rules; the design tokens --ax-font-sans, --ax-font-display and --ax-font-mono already point at these families.
Demo images, avatars & illustrations
All photos, product images, avatars and illustrations in the demo are placeholders for preview purposes only. Avatars are served from pravatar.cc and other imagery from placehold.co. They are not included in your license and must be replaced with your own assets before going to production. Vireo ships only its own brand mark; no third-party photography or illustration is redistributed with the template.
Deployment
Vireo ships as eight independent editions, and each one deploys the way its framework normally would. Whichever edition you choose, the workflow is the same three steps: install dependencies, produce a production build, then hand the output to a host. Run every command from the root of that edition's folder (the one containing its package.json).
All editions use Node.js to compile their assets with Vite (Next and Nuxt use their own CLI on top of it). Install a current LTS release of Node, then run npm install once inside an edition before building. The PHP-based editions (Laravel, Django, PHP) additionally need their own runtime installed to serve pages.
At a glance
| Edition | Build command | Deploy target |
|---|---|---|
| HTML | npm run build | Static output in dist/ — any static host, CDN, Netlify, Vercel, GitHub Pages |
| React | npm run build | Static output in dist/ — any static host, Netlify, Vercel, GitHub Pages |
| Vue | npm run build | Static output in dist/ — any static host, Netlify, Vercel, GitHub Pages |
| Next.js | npm run build | Vercel, or a Node server via npm run start |
| Nuxt | npm run build or npm run generate | Node server (build), or fully static (generate) on any static host |
| Laravel | npm run build + composer install | PHP host; web root points at public/ |
| Django | npm run build + collectstatic | WSGI/ASGI host (e.g. Gunicorn) behind a web server |
| PHP | npm run build | Any PHP host; web root points at public/ |
Static editions — HTML, React, Vue
These three compile down to plain HTML, CSS, and JavaScript. There is no server to run: build once, then upload the generated dist/ folder to any host that can serve static files.
npm install
npm run build
The finished site lands in dist/. Drag that folder into Netlify, connect the repository to Vercel, push it to a GitHub Pages branch, or copy it to any bucket, CDN, or shared host. To preview the production build locally before you deploy, run npm run preview.
The React and Vue editions are single-page apps that route on the client. If you host them under a subpath, or use deep links like /dashboard, configure your host to fall back to index.html for unknown routes so refreshes resolve correctly.
Next.js
The Next edition is a full framework build. The simplest path is Vercel: connect the repository and it detects Next automatically, running the build and serving it for you. To self-host, build and then start the bundled Node server:
npm install
npm run build
npm run start
By default npm run start serves on port 3000. Put it behind a reverse proxy (Nginx, a load balancer, or your platform's router) and keep the process alive with a manager such as PM2 or a systemd service.
Nuxt
Nuxt gives you two deployment shapes from the same codebase. Choose based on whether you want a running Node process or pure static files:
npm install
# Option A — Node server output
npm run build
node .output/server/index.mjs
# Option B — fully static output
npm run generate
With Option A, npm run build produces a self-contained server in .output/ that you run with Node (or preview locally via npm run preview). With Option B, npm run generate pre-renders every page into .output/public/, which you can upload to any static host, CDN, Netlify, or Vercel exactly like the static editions.
Laravel
The Laravel edition is a standard Laravel application, so it deploys to any PHP 8.3+ host. Install both the PHP and front-end dependencies, compile the assets, then configure the environment:
composer install --no-dev --optimize-autoloader
npm install
npm run build
cp .env.example .env
php artisan key:generate
php artisan migrate --force
Point your web server's document root at the edition's public/ directory — never at the project root — so application code stays outside the web path. Set your real values in .env (app URL, database, mail), and for best performance cache the framework config with php artisan config:cache and php artisan route:cache. Make sure storage/ and bootstrap/cache/ are writable by the web server.
Django
The Django edition runs on any host that can serve a WSGI/ASGI application. Install the Python and front-end dependencies, build the assets, then collect static files:
pip install -r requirements.txt
npm install
npm run build
python manage.py migrate
python manage.py collectstatic --noinput
Serve the app with a production server such as Gunicorn, placing a web server (Nginx, Caddy) in front of it:
gunicorn config.wsgi:application --bind 0.0.0.0:8000
Static assets are served through WhiteNoise, so collectstatic is all that is needed for CSS, JS, and fonts to load in production. Set DEBUG = False and configure ALLOWED_HOSTS for your domain before going live.
Plain PHP
The PHP edition needs no framework and no database — it runs on any standard PHP host, including inexpensive shared hosting. Build the assets, then upload the project:
npm install
npm run build
Set the web server's document root to the public/ folder. The included router.php lets you preview locally with PHP's built-in server (npm run serve), while on a real host Apache or Nginx handles routing to public/. Because the build output is committed alongside the source, you can upload the folder over FTP once assets are compiled.
For every server-rendered edition (Laravel, Django, PHP), always expose only the public/ directory to the web. Serving the project root would leave configuration and application files reachable over HTTP.
Frequently Asked Questions
Short, practical answers to the questions buyers ask most. If something here doesn't cover your case, the live demo and the rest of this documentation go into more depth.
Which edition should I use?
Pick the one that matches your stack. Use HTML for a plain static build or as a design reference; React, Vue, Next.js, or Nuxt for JavaScript-framework apps; and Laravel, Django, or PHP for server-rendered back ends. All eight editions share the same Aurora design, pages, and components, so the visual result is identical — only the underlying technology differs.
Do I need all the folders?
No. Each edition lives in its own top-level folder and is completely self-contained. Copy the single edition you plan to use into your project and ignore the rest — nothing is shared between them at runtime.
Can I use just the Tailwind classes?
Yes. Vireo is built on Tailwind CSS v4, and the markup uses standard utility classes plus a small set of design tokens (CSS variables) for theming. You are free to lift individual components, restyle with your own utilities, or extend the token set. There is no proprietary CSS framework to learn on top of Tailwind.
Is TypeScript required?
Only where the framework already expects it. The React, Vue, Next.js, and Nuxt editions are written in TypeScript because that is the modern norm for those ecosystems, and their build scripts type-check as part of the build. The HTML, Laravel, Django, and PHP editions use plain JavaScript. If you prefer JavaScript in a TypeScript edition, you can rename files and relax the compiler settings — TypeScript is a convenience here, not a hard dependency of the design.
Does it support dark mode and RTL?
Yes to both. Dark mode is built in and can follow the operating-system preference or be toggled manually, and the choice is remembered between visits. Full right-to-left (RTL) layout support is included as well, so the template works for languages such as Arabic and Hebrew out of the box.
How do I change the primary color?
The accent color is driven by a single CSS variable (--ax-accent) and its derived ramp, so you can recolor the entire interface in one place. The built-in theme customizer ships with 12 ready-made accent presets — Verdigris (the default), Amber, Amethyst, Cobalt, Forest, Graphite, Indigo, Magenta, Olive, Slate, Teal, and Terracotta — plus a custom picker that generates a full, contrast-correct color ramp from any hex value you enter. To lock in a permanent brand color, set the accent variable in your CSS rather than relying on the runtime customizer.
Are the demo images included for production?
The demo photos, avatars, and illustrations are provided for preview purposes only. They make the template look complete out of the box, but they are not licensed for redistribution in your own product. Replace them with your own imagery, or with assets you have the rights to, before shipping. See the Credits section for details on the preview media.
What browsers are supported?
Vireo targets modern evergreen browsers — recent versions of Chrome, Edge, Firefox, and Safari. The design leans on current CSS features (such as color-mix and custom properties) that these browsers support natively. It is not designed for legacy browsers like Internet Explorer.
Where are updates delivered?
Updates are delivered through ThemeForest. Sign in to your account and re-download Vireo from your Downloads page to get the latest version. The Changelog section lists what has changed in each release.
Support & Updates
Thank you for choosing Vireo. We want you to get up and running smoothly, so this section explains where to look first and how to reach out if you get stuck.
Before you reach out
Most questions are answered fastest by the material already in your download. Two places are worth checking first:
- This documentation, which walks through installation, building, deploying, theming, and the component structure of every edition.
- The live demo, which shows each page and feature working — a quick way to confirm expected behavior and inspect how a piece is put together.
Getting help
If you still need a hand, you can contact the author through the item's page on ThemeForest. Open the Vireo item and use the Comments tab for general questions, or the author's Support tab to request item support. Please include your edition (for example React or Laravel), your Node/PHP versions where relevant, and a clear description of what you expected versus what happened — that helps us help you quickly.
Support email: jawad.ahbab.turna@gmail.com
Updates
Vireo is updated through ThemeForest. When a new version is released, sign in to your account and re-download the item from your Downloads page — your purchase entitles you to the updates published for this item. The Changelog section records what changed in each release, so you can review it before upgrading. Because each edition is self-contained, upgrading is generally a matter of merging the changed files into your project; keep any customizations you have made in mind when you do.
If you have customized the template, keep your changes in version control (or a separate layer) so that pulling in a future update is a clean, reviewable merge rather than a manual re-apply.
Changelog
A record of what has changed in each release of Vireo. Re-download the item from your ThemeForest Downloads page to get the latest version.
v1.0.0 — 2026-07-02 — Initial release
- Eight framework editions: HTML, React, Vue, Next.js, Nuxt, Laravel, Django, and PHP.
- Around 185 pages per edition, covering dashboards, apps, forms, tables, charts, maps, authentication, and more.
- Aurora design system, shared consistently across every edition.
- Built-in dark mode with system-preference detection and manual toggle.
- Full right-to-left (RTL) layout support.
- Live theme customizer for switching layout, mode, and accent on the fly.
- 12 accent color presets, plus a custom accent picker.
Credits
Vireo is built on the shoulders of some excellent open-source work. We are grateful to the maintainers and communities behind the fonts, icons, and libraries below — the template would not be what it is without them.
Fonts
Typography is set in three typefaces, all served through Google Fonts:
- Inter — the primary UI and body typeface.
- Space Grotesk — used for headings and display text.
- JetBrains Mono — used for code, numeric, and monospaced content.
Icons
Tabler Icons — a large, consistent set of open-source SVG icons used throughout the interface.
Libraries
The editions rely on a small, focused set of libraries. Exactly which ones appear depends on the edition you are using:
- Tailwind CSS v4 — the utility-first CSS framework the entire design is built on.
- ApexCharts — the interactive charts and data visualizations, used in every edition.
- Leaflet — the interactive maps in the HTML, Laravel, Django, and PHP editions.
- Alpine.js — lightweight interactivity for the HTML, Laravel, Django, and PHP editions.
- React with React Router — the React edition.
- Vue with Vue Router — the Vue and Nuxt editions.
- Next.js — the Next.js edition (React-based).
- Nuxt — the Nuxt edition (Vue-based).
- Vite — the build tool that compiles assets across the editions.
- Laravel and Django — the respective server-rendered back-end editions.
Demo media
The photographs, avatars, and illustrations shown in the template are included for preview purposes only and are not licensed for redistribution in your own product. Please replace them with your own assets, or media you have the rights to, before deploying to production.
Each library is distributed under its own license; please refer to the respective projects for full license terms. Thank you again to every author and contributor whose work makes Vireo possible.