Vite Build
StatixFlow uses Vite 7 as the development server and production build tool. Vite compiles Tailwind CSS v4 from your source files, bundles JavaScript, and outputs ready-to-deploy HTML into the dist folder.
For Tailwind-specific setup details, see the official Tailwind + Vite guide .
If you only need to tweak text or images on finished pages, see Customize Production Ready HTMLs. Use this guide when you change HTML structure, add Tailwind classes, edit CSS or JavaScript under assets/, or need a fresh production build.
Prerequisites
- Install Node.js (Vite 7 requires Node.js version 20.19+, 22.12+.).
- Open a terminal in the root of the downloaded template (the folder that contains
package.json,vite.config.ts, and your.htmlfiles). - See File Structure if you are unsure which folder is the project root.
Install dependencies
From the template root:
npm installThis reads package.json and package-lock.json and installs packages into node_modules.
npm scripts reference
| Script | Command | Purpose |
|---|---|---|
dev | vite --host | Local development with hot reload |
build | node build.js | Production build into dist |
Development
Start the Vite dev server with live reload:
npm run devVite serves the project on your local network (--host is enabled in the dev script). Open the URL shown in the terminal—typically http://localhost:5173—and navigate to the HTML page you are editing (for example index.html).
While the dev server is running, edit files in the project root and under assets/ —not in dist.
- HTML — Change page structure and content in
.htmlfiles at the project root (for exampleindex.html,about.html). To add a brand-new page, follow Adding a new HTML page. - JavaScript — Adjust behavior in
assets/js/.
Styling with Tailwind
Style pages with Tailwind utility classes on your HTML elements—classes such as flex, gap-4, text-sm, and bg-primary. With the dev server running, Vite compiles any new or updated utilities into CSS automatically. See the Tailwind CSS documentation for utility class reference, responsive design, and v4 features.
When you need styling that is shared across pages or goes beyond a single utility, open assets/css/style.css. That file is the template’s main stylesheet (linked from each HTML page) and is where you:
- Define design tokens — theme colors, fonts, and variables (
:root,@theme). - Add custom utility classes — reusable utilities in
@layer utilities(for examplebg-white-stripe). - Add component styles — repeated patterns in
@layer components(for example Swiper pagination or scroll-highlight links).
Default theme variables
The template ships with a small semantic color palette and one typography token. Values are declared in :root, then exposed to Tailwind through @theme inline so you can use them as utilities (bg-primary, text-muted-foreground, border-border, and so on).
How it works
:root— Raw CSS custom properties (for example--primary,--background). Edit these when you want to change the theme globally.@theme/@theme inline— Maps those properties to Tailwind’s--color-*and--font-*namespace so the compiler generates matching utilities.@layer base— Applies defaults to the page (for examplebodyusesbg-backgroundandtext-foreground).
Typography
| Token | Default | Tailwind usage |
|---|---|---|
--font-sans | "Instrument Sans", sans-serif | font-sans |
Semantic colors
| Role | CSS variable (:root) | Default (summary) | Example utilities |
|---|---|---|---|
| Page | --background, --foreground | Slate-50 page, dark green-tinted text | bg-background, text-foreground |
| Brand | --primary, --primary-foreground | Neutral-900 / white | bg-primary, text-primary-foreground |
| Accent brand | --secondary, --secondary-foreground | Blue-800 / blue-50 | bg-secondary, text-secondary-foreground |
| Muted | --muted, --muted-foreground | Gray-200 / gray-blue text | bg-muted, text-muted-foreground |
| Highlight | --accent, --accent-foreground | Violet-100 / violet-700 | bg-accent, text-accent-foreground |
| Border | --border | Light neutral (oklch) | border-border |
| Card | --color-card, --color-card-foreground (via @theme inline) | White card on --foreground text | bg-card, text-card-foreground |
| Focus ring | --color-ring (via @theme inline) | 15% primary mix | ring-ring |
| Input | --color-input (via @theme inline) | Same as border | border-input |
Certain color variables come in pairs: a surface token for the background and a matching foreground token for the text as shown for example in the Brand and Accent brand colors above.
Status colors (alerts, badges, feedback UI)
| Role | Example utilities |
|---|---|
| Success | bg-status-success, text-status-success-foreground |
| Info | bg-status-info, text-status-info-foreground |
| Warning | bg-status-warning, text-status-warning-foreground |
| Destructive | bg-status-destructive, text-status-destructive-foreground |
Other
| Token | Purpose |
|---|---|
--stripe-opacity | Opacity for custom stripe utilities (bg-white-stripe, diagonal variants) — default 18% |
:root defaults (excerpt)
:root {
--background: var(--color-slate-50);
--foreground: oklch(0.1445 0.0148 121.37);
--primary: var(--color-neutral-900);
--primary-foreground: var(--color-white);
--secondary: var(--color-blue-800);
--secondary-foreground: var(--color-blue-50);
/* status-success, status-info, status-warning, status-destructive … */
--muted: var(--color-gray-200);
--muted-foreground: oklch(0.6 0.03 251.66);
--accent: var(--color-violet-100);
--accent-foreground: var(--color-violet-700);
--border: oklch(0.9097 0 0);
--stripe-opacity: 18%;
}Bridging into Tailwind (@theme inline)
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
/* …maps every semantic token to --color-* … */
--color-ring: color-mix(in oklch, var(--color-primary) 15%, transparent);
--color-card: var(--color-white);
--color-card-foreground: var(--foreground);
}To rebrand the template, adjust the values under :root in assets/css/style.css (and @theme if you add new font families).
Adding a new HTML page
Vite treats every .html file in the project root (next to package.json) as its own page entry. When you add a new template—for example services.html—place it there, not inside dist/. The file is picked up automatically by npm run dev and included in npm run build with no extra Vite configuration.
The fastest approach is to duplicate an existing page that is closest to what you need (contact.html or privacy-policy.html for a simple inner page, index.html for a full landing layout), rename the file, then edit the title, navigation links, and main content.
Basic page structure
Below is a basic page skeleton. Key details are included in the HTML comments:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- Favicon and Viewport -->
<link rel="icon" type="image/svg+xml" href="/imgs/generic/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400..700;1,400..700&display=swap"
rel="stylesheet"
/>
<!-- Main Stylesheet -->
<!-- For Production Mode, it'll be <link href="assets/css/style.min.css" rel="stylesheet" /> this is done automatically when you run npm run build -->
<link href="assets/css/style.css" rel="stylesheet" />
<!-- Page Description -->
<meta name="description"
content="StatixFlow is a premium platform designed to optimize performance, growth strategy, and automate your business processes." />
<!-- Page Title -->
<title>Your Page Title - StatixFlow</title>
</head>
<body>
<!-- Start: Page Header -->
<header class="fixed top-0 right-0 left-0 z-50 py-4" data-animated-scroll-header>
<div class="container mx-auto px-4">
<div class="flex items-center justify-between rounded-2xl bg-white p-4 shadow-xl sm:py-2">
<!-- Start: Logo -->
<a href="index.html" class="flex items-center gap-2 text-sm font-bold tracking-wider uppercase">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
<path d="M13 3L4 14h7l-2 7 9-11h-7l2-7z" />
</svg>
<span>StatixFlow™</span>
</a>
<!-- End: Logo -->
<!-- Start: XL+ Screens Navigation -->
<nav class="hidden items-center gap-10 text-sm font-medium xl:flex" data-desktop-nav>
<a href="home.html" data-active-link
class="text-foreground transition-colors duration-300 ease-in-out hover:text-foreground/70 data-active-link:text-muted-foreground">Home</a>
<a href="about.html"
class="text-foreground transition-colors duration-300 ease-in-out hover:text-foreground/70 data-active-link:text-muted-foreground">About</a>
...
</nav>
<!-- End: XL+ Screens Navigation -->
<!-- Start: Header Actions -->
<div class="flex items-center gap-6">
<!-- Start: Header CTA Button -->
<a href="#"
class="group hidden items-center justify-center gap-2 rounded-full border border-primary bg-transparent px-4 py-3 text-sm font-medium text-black sm:inline-flex">
<span class="relative overflow-hidden">
<span
class="relative block h-full translate-y-0 transition-transform duration-300 ease-in-out group-hover:-translate-y-full">Send
a message</span>
<span
class="absolute top-0 left-0 block h-full translate-y-full transition-transform duration-300 ease-in-out group-hover:translate-y-0">Send
a message</span>
</span>
<span class="translate-x-0 transition-transform duration-300 ease-in-out group-hover:translate-x-2">
<i data-lucide="chevron-right" class="size-4"></i>
</span>
</a>
<!-- End: Header CTA Button -->
<!-- Start: Mobile Navigation Trigger -->
<button class="group flex cursor-pointer items-center gap-2 xl:hidden" data-mobile-nav-trigger>
<span class="text-xs font-medium tracking-widest text-foreground uppercase">Menu</span>
<span class="flex h-3 w-4 flex-col justify-between">
<span
class="block h-px w-full origin-center bg-current transition-all duration-300 ease-in-out group-open:translate-y-[5.5px] group-open:rotate-45"></span>
<span
class="block h-px w-full origin-center bg-current transition-all duration-300 ease-in-out group-open:opacity-0"></span>
<span
class="block h-px w-full origin-center bg-current transition-all duration-300 ease-in-out group-open:-translate-y-[5.5px] group-open:-rotate-45"></span>
</span>
</button>
<!-- End: Mobile Navigation Trigger -->
</div>
<!-- End: Header Actions -->
</div>
</div>
</header>
<!-- End: Page Header -->
<!-- Start: Mobile Navigation Overlay -->
<div
class="pointer-events-none fixed inset-0 z-60 bg-black/40 opacity-0 transition-all duration-300 ease-in-out open:pointer-events-auto open:opacity-100"
data-mobile-nav-overlay></div>
<!-- End: Mobile Navigation Overlay -->
<!-- Start: Mobile Navigation Sheet -->
<div
class="fixed top-0 left-0 z-70 flex h-screen w-3/4 -translate-x-full flex-col bg-black text-white transition-transform duration-300 ease-in-out open:translate-x-0"
data-mobile-nav-sheet>
<div class="flex min-h-0 flex-1 flex-col justify-between overflow-y-auto p-10 md:p-20">
<div class="grid grid-cols-1 gap-8 md:grid-cols-[180px_1fr] md:gap-10">
<!-- Social -->
<div>
<h2 class="mb-6 text-xs font-medium tracking-widest text-muted-foreground uppercase">
Social
</h2>
<ul class="space-y-4 text-lg sm:space-y-6">
<li>
<a href="#"
class="flex items-center gap-2 opacity-100 transition-opacity duration-300 ease-in-out hover:opacity-70"
data-mobile-nav-link aria-label="Follow us on X (Twitter)">
<img src="/imgs/social/light/x.svg" alt="X" width="48" height="48" class="size-4" loading="lazy" />
<span>X (Twitter)</span>
</a>
</li>
...
</ul>
</div>
<!-- End: Social -->
<!-- Start: Menu -->
<div>
<h2 class="mb-6 text-xs font-medium tracking-widest text-muted-foreground uppercase">
Menu
</h2>
<ul class="space-y-4 text-lg font-medium sm:space-y-6 md:text-4xl">
<li>
<a href="home.html"
class="transition-opacity duration-300 ease-in-out hover:opacity-70 data-active-link:text-muted-foreground" data-active-link
data-mobile-nav-link>Home</a>
</li>
<li>
<a href="about.html"
class="transition-opacity duration-300 ease-in-out hover:opacity-70 data-active-link:text-muted-foreground"
data-mobile-nav-link>About</a>
</li>
...
</ul>
</div>
<!-- End: Menu -->
</div>
<!-- Start: Other information -->
<div class="mt-auto pt-8 md:pt-10">
<p class="mb-6 text-xs font-medium tracking-widest text-muted-foreground uppercase">
Get in touch
</p>
<a href="mailto:info@statixflow.com"
class="text-lg font-medium transition-opacity duration-300 ease-in-out hover:opacity-70">info@statixflow.com</a>
</div>
<!-- End: Other information -->
</div>
</div>
<!-- End: Mobile Navigation Sheet -->
<!-- Start: Smooth Scroll Area -->
<div id="smooth-wrapper">
<div id="smooth-content">
<!-- For smooth scroll to work as expected, all content should be inside #smooth-wrapper & #smooth-content. All fixed position elements should be outside of #smooth-wrapper -->
<!-- Start: Main Container -->
<main data-main-container>
<!-- ... All main sections/divs go here ... -->
<!-- Copy <footer> from an existing page when you need the standard site footer -->
</main>
<!-- End: Main Container -->
</div>
</div>
<!-- End: Smooth Scroll Area -->
<!-- Main JavaScript -->
<!-- For Production Mode, it'll be <script src="assets/js/main.min.js"></script> this is done automatically when you run npm run build -->
<script type="module" src="assets/js/main.js"></script>
</body>
</html>Assets and internal links
- Images and static files — Place files in
public/and reference them with a leading slash, for examplesrc="/imgs/hero/photo.jpg". - Links between pages — Use sibling
.htmlpaths from the project root, for examplehref="contact.html"orhref="index.html". - In-page anchors — Use
href="#section-id"; smooth scrolling for hash links is handled when the smooth-scroll wrapper is present.
Checklist after adding a page
- Save the new
.htmlfile in the project root. - Update navigation links in the header and mobile menu on other pages if the page should appear in the menu.
- Run
npm run devand openhttp://localhost:5173/your-page.html. - Run
npm run buildand confirm the new file appears indist/before deployment.
Production build
Generate optimized output for deployment:
npm run buildThe build.js file which is powered by Vite, writes compiled HTML, CSS, and JavaScript to the dist folder. Upload the contents of dist to your host, or use that folder as the publish root in your deployment pipeline.
Code formatting (Prettier)
Prettier is a developer tool for formatting source files. It does not run during npm run dev or npm run build and is not required to deploy the site.
The template ships with Prettier and prettier-plugin-tailwindcss in devDependencies. .prettierrc enables the Tailwind plugin and tells it which stylesheet defines your theme:
{
"plugins": ["prettier-plugin-tailwindcss"],
"tailwindStylesheet": "./assets/css/style.css"
}| Setting | Purpose |
|---|---|
plugins | Sorts Tailwind utility classes in class attributes into a stable, recommended order when you format a file. |
tailwindStylesheet | Must match the main stylesheet linked from your HTML (assets/css/style.css). The plugin reads it so sorting respects custom utilities and semantic tokens from @theme (for example bg-primary, text-muted-foreground). |
Use Prettier from your editor (format on save) or from the template root:
npx prettier --write .There is no format script in package.json. If you change the path to your main CSS file, update tailwindStylesheet in .prettierrc to match.
Troubleshooting
npm install or npm run dev fails immediately
- Confirm
node -vis 20.19+ or 22.12+. - Delete
node_modulesand runnpm installagain. - Use npm 9+ if the lockfile causes install errors on an older npm.
Tailwind classes do not appear after editing HTML
- Run
npm run devornpm run buildso Tailwind can compile utilities into CSS. Editingdistalone will not pick up new classes (see Customize Production Ready HTMLs).