Creating Custom Theme
Since Venta Theme 1.6.0 the build stack is TailwindCSS v4 (CSS-first @theme, standalone CLI, no PostCSS). A custom theme built on Venta Theme follows the same v4 pipeline. If you are migrating an existing v3 child theme instead of creating a new one, follow Updating to 1.6.0 first.
The setup below mirrors the Venta Theme demo, which ships a BaseTheme (a direct Venta Theme child) and a ChildTheme (a child of BaseTheme).
Prerequisites
- Node.js 20 or higher (required by Hyvä).
- Venta Theme 1.6.0 or higher installed via Composer, with
npm cialready run in itsweb/tailwind/directory (see Installation).
1. Create the Magento theme
Create a new theme with the official Magento docs and set the parent theme to Magebit/venta.
2. Base theme (direct Venta Theme child)
This is the theme that extends Magebit/venta directly. It is the theme that builds the JS bundle (see JS bundle). Create a web/tailwind folder under it and add the files below.
.gitignore
node_modules/
generated/generated/ holds the auto-generated Hyvä source/token files and the extension bundle list. They are rebuilt by npm run generate / npm run rebuild-js and must not be committed.
package.json and package-lock.json
Copy both from Venta Theme. Since 1.6.0 they carry the v4 scripts, including the esbuild JS bundle (rebuild-js):
cp vendor/magebitcom/magento2-venta-theme/web/tailwind/package.json app/design/frontend/<Vendor>/<BaseTheme>/web/tailwind/
cp vendor/magebitcom/magento2-venta-theme/web/tailwind/package-lock.json app/design/frontend/<Vendor>/<BaseTheme>/web/tailwind/The scripts that matter:
"scripts": {
"rebuild-js": "node esbundle.mjs",
"generate": "npx hyva-sources && npx hyva-tokens",
"watch": "NODE_ENV=development npx tailwindcss -i tailwind-source.css -o ../css/styles.css --watch",
"build": "NODE_ENV=production npx tailwindcss -i tailwind-source.css -o ../css/styles.css --minify",
"build-prod": "npm run generate && npm run rebuild-js && npm run build && npm run output-success"
}build-prod runs generate (Hyvä sources and tokens), then rebuild-js (the esbuild JS bundle), then build (the CSS). esbuild is a production dependency for this reason.
esbundle.mjs
Copy it from Venta Theme. It builds the theme JS bundle and scans every module for extension JS:
cp vendor/magebitcom/magento2-venta-theme/web/tailwind/esbundle.mjs app/design/frontend/<Vendor>/<BaseTheme>/web/tailwind/venta-bundle.js
This is the esbuild entry point. It imports Venta Theme's bundled JS straight from the vendor package so it tracks Venta upgrades, then pulls in the locally generated extension bundle:
/**
* @author Magebit <info@magebit.com>
* @copyright Copyright (c) Magebit, Ltd. (https://magebit.com)
* @license https://magebit.com/code-license
*/
import '../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/js/bundle/modal.js';
import '../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/js/bundle/snap-slider.js';
import '../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/js/bundle/configurable-options.js';
import '../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/js/bundle/messages.js';
import '../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/js/bundle/cart-drawer.js';
/* Extension JS discovered by esbundle.mjs through module venta-bundle/ directories */
import './generated/extension-bundle.js';tailwind-source.css
Import order is critical: Hyvä modules first, then TailwindCSS with source(none), then Venta Theme's layers, then the generated files. A pure pass-through base theme stops here; add your own layers last (see the child theme for the override pattern).
/**
* @copyright Copyright (c) 2026 Magebit, Ltd. (https://magebit.com/)
* @author Magebit <info@magebit.com>
* @license MIT
*/
@import "@hyva-themes/hyva-modules/css";
@import "tailwindcss" source(none);
@source "../../**/*.phtml";
@source "../../**/*.xml";
/* Venta Theme variables */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/theme.css";
/* Venta Theme Base Layer */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/base/index.css";
/* Venta Theme Components */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/components/index.css";
/* Venta Theme Utilities */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/utilities/index.css";
/* Venta Theme global theme layer */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/theme/index.css";
/* Generated styles for Hyvä-compatible modules and design tokens */
@import "./generated/hyva-source.css";
@import "./generated/hyva-tokens.css";INFO
v4 requires the ./ prefix on relative @import paths. @import "base" without ./ will not resolve.
hyva.config.json
Controls which paths are scanned for TailwindCSS class names and which design tokens are generated. Include only paths not already registered in app/etc/hyva-themes.json (Magebit modules self-register there after bin/magento setup:upgrade):
{
"tailwind": {
"include": [
{ "src": "vendor/hyva-themes/magento2-default-theme" },
{ "src": "vendor/magebitcom/magento2-venta-theme" }
],
"exclude": [
{ "src": "vendor/hyva-themes/magento2-hyva-checkout/src" }
]
}
}TIP
If you have custom modules under app/code whose templates use TailwindCSS classes, add { "src": "app/code" } to include.
WARNING
If your project uses Venta Theme checkout, keep the magento2-hyva-checkout/src exclude to avoid CSS specificity conflicts. See Updating to 1.6.0, §2 for the full explanation and the keepSource option.
After any change to hyva.config.json, regenerate with npm run generate.
3. Child theme (extends your base theme)
For multiple websites sharing one base, use a Base → Child hierarchy so each child holds only its own differences. Create the child theme with its parent set to your base theme, then add a web/tailwind folder.
A child theme does not build its own JS bundle. It has no esbundle.mjs or venta-bundle.js, and its package.json omits the rebuild-js step. Magento's theme fallback serves the base theme's compiled web/js/venta-bundle.min.js.
package.json
Same as the base theme, but build-prod drops rebuild-js and esbuild moves to devDependencies:
"scripts": {
"generate": "npx hyva-sources && npx hyva-tokens",
"watch": "NODE_ENV=development npx tailwindcss -i tailwind-source.css -o ../css/styles.css --watch",
"build": "NODE_ENV=production npx tailwindcss -i tailwind-source.css -o ../css/styles.css --minify",
"build-prod": "npm run generate && npm run build && npm run output-success"
}tailwind-source.css
Imports Venta Theme's layers and the generated files, then the base theme's layers, then the child's own layers last so they win by source order:
/**
* @copyright Copyright (c) 2026 Magebit, Ltd. (https://magebit.com/)
* @author Magebit <info@magebit.com>
* @license MIT
*/
@import "@hyva-themes/hyva-modules/css";
@import "tailwindcss" source(none);
@source "../../**/*.phtml";
@source "../../**/*.xml";
/* Venta Theme variables */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/theme.css";
/* Venta Theme Base Layer */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/base/index.css";
/* Venta Theme Components */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/components/index.css";
/* Venta Theme Utilities */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/utilities/index.css";
/* Generated styles for Hyvä-compatible modules and design tokens */
@import "./generated/hyva-source.css";
@import "./generated/hyva-tokens.css";
/* Venta Theme global theme layer */
@import "../../../../../../../vendor/magebitcom/magento2-venta-theme/web/tailwind/theme/index.css";
/* Child theme custom layers - imported last to override by source order */
@import "./base";
@import "./components";
@import "./utilities";
@import "./theme/index.css";INFO
Create only the layer folders you need (base/, components/, utilities/, theme/), each with an index.css that imports its partials, and omit the matching @import line for any folder you do not create.
hyva.config.json
Adds the base theme to include so its templates are scanned, and defines the child's design tokens under tokens:
{
"tailwind": {
"include": [
{ "src": "vendor/hyva-themes/magento2-default-theme" },
{ "src": "vendor/magebitcom/magento2-venta-theme" },
{ "src": "app/design/frontend/<Vendor>/<BaseTheme>" }
],
"exclude": [
{ "src": "vendor/hyva-themes/magento2-hyva-checkout/src" }
]
},
"tokens": {
"values": {
"color": {
"primary": {
"lighter": "#4a90e2",
"DEFAULT": "#2563eb",
"darker": "#1e40af"
}
}
}
}
}TIP
Tokens can be defined in hyva.config.json (above, generated into hyva-tokens.css) or as a CSS @theme {} block in a layer file. For the @theme approach and the full token naming rules, see Updating to 1.6.0, §3.
JS bundle
Since 1.6.3 the theme ships a static JS bundle at web/js/venta-bundle.min.js, built by esbuild (esbundle.mjs, run via npm run rebuild-js) and loaded deferred from the page head. It contains the modal library, SnapSlider plugin, configurable product options, the message list, and the cart drawer.
A module adds its JS to the bundle by placing browser-cacheable, translation-free scripts in:
<module>/view/frontend/web/js/venta-bundle/*.jsesbundle.mjs scans every module under app/code and vendor for that directory and compiles whatever it finds into the bundle. Page-specific values (translations, config) are passed separately through small inline window.ventaBundleConfig bridges emitted by the module's templates. Because the bundle is built from whatever is on disk, installing or removing such a module requires rebuilding the bundle (npm run rebuild-js, or just build-prod), the same rule that already applies to the TailwindCSS build.
Only the direct Venta Theme child (your base theme) builds the bundle; it scans the whole project, so child themes inherit the complete bundle through Magento's theme fallback.
Compile the theme
Each theme is compiled independently:
npm --prefix app/design/frontend/<Vendor>/<theme>/web/tailwind ci
npm --prefix app/design/frontend/<Vendor>/<theme>/web/tailwind run build-prodOn the base theme, build-prod rebuilds the CSS and the JS bundle; on a child theme it rebuilds the CSS only.
INFO
Venta Theme itself must have npm ci run in its own web/tailwind/ directory (see Installation) before any child theme will compile.
After compilation, set the theme under Content → Design → Configuration in the Admin panel.