Install the kit
This guide installs the kit in an Express application using EJS. The direct path uses the precompiled CSS; the custom path adds Tailwind to customize the theme and components sustainably. Internationalization is optional, with English as the fallback and French available.
Generate the portable export
From the UI kit repository, install its dependencies, build the CSS, then generate the kit/ directory.
cd /chemin/vers/ui-kit
npm install
npm run build:css
npm run export:kit
Choose an installation method
Switch between the two procedures. Each tab includes every step needed after the export is generated.
Direct installation
The target project uses the compiled CSS provided by the export directly, without an additional Tailwind pipeline.
Copy the files into the application
Only adjust the views root if your project does not use src/views.
kit/views/ui/ → src/views/ui/
kit/public/ → public/
kit/src/helpers/ → src/helpers/
# Optional SSR internationalization
kit/src/i18n/ → src/i18n/
# Optional layouts
kit/views/layouts/ → src/views/layouts/
Important: Keep the public/ structure. Floating UI, Quill, Prism, and Chart.js bundles are already included there.
Install dependencies
Front-end libraries remain provided as static files.
npm install express ejs express-ejs-layouts lucide
SSR internationalization is optional. Install i18next only if you enable the server middleware:
npm install i18next
Configure Express and the icon helper
Expose static files and make icon and uiIcon available in every template.
import express from 'express';
import expressLayouts from 'express-ejs-layouts';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { renderIcon } from './helpers/icon.js';
// Optional SSR internationalization:
// import { createUIKitI18nMiddleware } from './i18n/index.js';
const currentDirectory = dirname(fileURLToPath(import.meta.url));
const app = express();
app.set('view engine', 'ejs');
app.set('views', join(currentDirectory, 'views'));
app.set('layout', 'layouts/main');
app.set('layout extractScripts', true);
app.use(expressLayouts);
// Enable one of the documented i18n modes when needed.
// app.use(createUIKitI18nMiddleware({ enabled: true, locale: 'fr', detection: false }));
app.use((req, res, next) => {
res.locals.icon = renderIcon;
res.locals.uiIcon = renderIcon;
res.locals.currentPath = req.path;
next();
});
app.use(express.static(join(currentDirectory, '..', 'public')));
Load the CSS and browser runtime
The layout loads the exported public/app.css file directly.
<!DOCTYPE html>
<html lang="<%= locale || 'en' %>"
data-ui-locale="<%= locale || 'en' %>"
data-ui-i18n="<%= uiI18n?.enabled ? 'enabled' : 'disabled' %>">
<head>
<link rel="stylesheet" href="/app.css" />
<script type="importmap">
{
"imports": {
"@floating-ui/core": "/floating-ui-core/floating-ui.core.browser.min.mjs"
}
}
</script>
</head>
<body>
<%- typeof script !== 'undefined' ? script : '' %>
<script>window.__UIKIT_I18N__ = <%- JSON.stringify(uiI18n || { enabled: false, locale: locale || 'en' }) %>;</script>
<script type="module" src="/ui/loader.js"></script>
</body>
</html>
Render a first component
In a page under src/views/pages, add a kit partial. The loader automatically detects interactive components.
<%- include('../ui/alert', {
variant: 'success',
title: 'Kit installé',
message: 'Votre premier composant est opérationnel.',
dismissible: true,
}) %>
Custom installation
The target project rebuilds the kit with Tailwind and can modify tokens and component styles.
Copy the files into the application
Only adjust the views root if your project does not use src/views.
kit/views/ui/ → src/views/ui/
kit/public/ → public/
kit/src/helpers/ → src/helpers/
# Optional SSR internationalization
kit/src/i18n/ → src/i18n/
# Optional layouts
kit/views/layouts/ → src/views/layouts/
# Sources required for the custom build
kit/assets/css/ → assets/css/
kit/tailwind.config.js → tailwind.config.js
Important: Keep the public/ structure. Floating UI, Quill, Prism, and Chart.js bundles are already included there.
Install dependencies
Tailwind is added to development dependencies to build the theme.
npm install express ejs express-ejs-layouts lucide
npm install -D tailwindcss
SSR internationalization is optional. Install i18next only if you enable the server middleware:
npm install i18next
Configure Express and the icon helper
Expose static files and make icon and uiIcon available in every template.
import express from 'express';
import expressLayouts from 'express-ejs-layouts';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { renderIcon } from './helpers/icon.js';
// Optional SSR internationalization:
// import { createUIKitI18nMiddleware } from './i18n/index.js';
const currentDirectory = dirname(fileURLToPath(import.meta.url));
const app = express();
app.set('view engine', 'ejs');
app.set('views', join(currentDirectory, 'views'));
app.set('layout', 'layouts/main');
app.set('layout extractScripts', true);
app.use(expressLayouts);
// Enable one of the documented i18n modes when needed.
// app.use(createUIKitI18nMiddleware({ enabled: true, locale: 'fr', detection: false }));
app.use((req, res, next) => {
res.locals.icon = renderIcon;
res.locals.uiIcon = renderIcon;
res.locals.currentPath = req.path;
next();
});
app.use(express.static(join(currentDirectory, '..', 'public')));
Configure the CSS build and layout
CSS is generated in public/app.css before the layout loads it.
# package.json
"scripts": {
"dev:css": "tailwindcss -i ./assets/css/input.css -o ./public/app.css --watch",
"build:css": "tailwindcss -i ./assets/css/input.css -o ./public/app.css --minify"
}
npm run build:css
Edit assets/css/tokens.css for the theme and assets/css/input.css for components. Do not edit public/app.css directly.
<!DOCTYPE html>
<html lang="<%= locale || 'en' %>"
data-ui-locale="<%= locale || 'en' %>"
data-ui-i18n="<%= uiI18n?.enabled ? 'enabled' : 'disabled' %>">
<head>
<link rel="stylesheet" href="/app.css" />
<script type="importmap">
{
"imports": {
"@floating-ui/core": "/floating-ui-core/floating-ui.core.browser.min.mjs"
}
}
</script>
</head>
<body>
<%- typeof script !== 'undefined' ? script : '' %>
<script>window.__UIKIT_I18N__ = <%- JSON.stringify(uiI18n || { enabled: false, locale: locale || 'en' }) %>;</script>
<script type="module" src="/ui/loader.js"></script>
</body>
</html>
Render a first component
In a page under src/views/pages, add a kit partial. The loader automatically detects interactive components.
<%- include('../ui/alert', {
variant: 'success',
title: 'Kit installé',
message: 'Votre premier composant est opérationnel.',
dismissible: true,
}) %>
Optional internationalization
When internationalization is disabled, the kit does not initialize i18next or detect a preference. For SSR, install i18next then use the exported middleware. It exposes locale, t and uiI18n to templates and configures browser rendering.
Files included in the export
src/i18n/: server helper and catalogspublic/ui/i18n.js: browser initializationpublic/ui/locales/: English/French common, component and layout catalogspublic/i18next/: local runtime without a CDN
import { createUIKitI18n } from './i18n/index.js';
// Default behavior: no i18next initialization or language detection.
const uiI18n = createUIKitI18n({ enabled: false });
import { createUIKitI18nMiddleware } from './i18n/index.js';
app.use(createUIKitI18nMiddleware({
enabled: true,
locale: 'en',
detection: false,
}));
import { createUIKitI18nMiddleware } from './i18n/index.js';
app.use(createUIKitI18nMiddleware({
enabled: true,
locale: 'fr',
detection: false,
}));
import { createUIKitI18nMiddleware } from './i18n/index.js';
app.use(createUIKitI18nMiddleware({
enabled: true,
detection: true,
resolveLocale: request => request.user?.locale,
}));
An unknown locale falls back to en. A fixed locale takes precedence over request, cookie, or browser preferences. Values and labels explicitly supplied by the application remain prioritized over internal translations.
Installation complete
- •
/app.cssresponds without errors - •
/ui/loader.jsresponds without errors - • icons are rendered server-side
- • interactive components work with the keyboard
- • dark mode does not flash
- • the production CSS build completes