Express + EJS

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.

1

Generate the portable export

From the UI kit repository, install its dependencies, build the CSS, then generate the kit/ directory.

UI kit repository Bash
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.

2

Copy the files into the application

Only adjust the views root if your project does not use src/views.

Folder mapping Text
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.

3

Install dependencies

Front-end libraries remain provided as static files.

Target application Bash
npm install express ejs express-ejs-layouts lucide

SSR internationalization is optional. Install i18next only if you enable the server middleware:

SSR i18n (optional) Bash
npm install i18next

4

Configure Express and the icon helper

Expose static files and make icon and uiIcon available in every template.

src/app.js Js
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')));

5

Load the CSS and browser runtime

The layout loads the exported public/app.css file directly.

Layout EJS Html
<!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>

6

Render a first component

In a page under src/views/pages, add a kit partial. The loader automatically detects interactive components.

src/views/pages/example.ejs Ejs
<%- 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 catalogs
  • public/ui/i18n.js : browser initialization
  • public/ui/locales/ : English/French common, component and layout catalogs
  • public/i18next/ : local runtime without a CDN
Recommendation: Use a fixed locale for exports, back offices, and environments without a browser preference. Automatic detection must be explicitly enabled.
Internationalization disabled Js
import { createUIKitI18n } from './i18n/index.js';

// Default behavior: no i18next initialization or language detection.
const uiI18n = createUIKitI18n({ enabled: false });

Fixed English, without detection Js
import { createUIKitI18nMiddleware } from './i18n/index.js';

app.use(createUIKitI18nMiddleware({
  enabled: true,
  locale: 'en',
  detection: false,
}));

Fixed French, without detection Js
import { createUIKitI18nMiddleware } from './i18n/index.js';

app.use(createUIKitI18nMiddleware({
  enabled: true,
  locale: 'fr',
  detection: false,
}));

Automatic detection (opt-in) Js
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.css responds without errors
  • /ui/loader.js responds without errors
  • • icons are rendered server-side
  • • interactive components work with the keyboard
  • • dark mode does not flash
  • • the production CSS build completes