MageObsidian Theme¶
MageObsidian Theme is the reference storefront theme built entirely with MageObsidian Components. It replaces Magento's Luma frontend with a modern stack β Twig templates, Vite, TailwindCSS 4, and lazy-hydrated Vue islands β while keeping Magento's native layouts, blocks, and view models. It is already functional and covers the same ground as Luma (catalog, checkout, customer, search, cart, wishlist, compare, reviews, and sales).
This page is a practical guide to using and extending the theme. For the underlying mechanism shared by every compatible theme, see Compatibility Themes.
Compatibility
- β Magento Open Source 2.4.7+ β supported today.
- π§ͺ Adobe Commerce and Mage-OS β technically compatible since core 2.6.0, but not fully tested yet.
Architecture: two layers¶
The theme ships as two stacked themes so design is cleanly separated from plumbing:
-
MageObsidian/theme-base
The neutral, technical foundation: build wiring and structural templates, without any design tokens. This is the parent you usually inherit from when starting a brand-new look.
Package:
mage-obsidian/theme-base -
MageObsidian/default
The OBSIDIAN skin: design tokens, styled Twig templates, and a replaceable apparel demo layer. Inherit from it when you want to keep OBSIDIAN and tweak; replace its tokens to rebrand.
Package:
mage-obsidian/theme-default
The storefront logic β view models, legacy-layout neutralization, and shared Vue islands β lives in
the mage-obsidian/module-storefront repository, pulled
in automatically by theme-base.
Inheritance is declared with Magento's native theme.xml:
A theme directory looks like this:
Install & activate¶
-
Require the theme with Composer.
mage-obsidian/theme-defaultpulls intheme-base, the modern-frontend engine, and the full storefront module stack (Luma-level parity) automatically: -
Select it in the Admin under Stores β Configuration β General β Design β Design Theme (or via
bin/magento config:set), then apply it to your store view. -
Regenerate the PHP β JS contract so the build engine sees the theme:
-
Build the frontend assets to disk:
See Installation for first-time setup.
Develop with live reload (HMR)¶
For day-to-day work, run the Vite dev server so edits to .vue, CSS, and Twig hot-reload in the
browser. Enable HMR and wire nginx once, then start the server per session:
The nginx snippet proxies /static requests to the Vite dev server β host and port come from your
config, you don't hand-pick them. HMR is ignored in production mode. Full walkthrough and
troubleshooting in HMR Configuration and
Development Workflow.
Deploy to production¶
There is no separate build step. MageObsidian hooks into Magento's standard static-content deploy: its plugins exclude modern themes from the legacy Less/RequireJS pipeline and inject the Vite output (minified, tree-shaken, hashed) as part of the normal command:
Only themes shipping etc/mage_obsidian_compatibility.xml go through the Vite pipeline; everything
else follows Magento's native deploy untouched. See
Building Static Assets.
Re-theme it: design tokens¶
Re-skinning OBSIDIAN is CSS-first: every color, font, radius, and easing lives in the
@theme block of web/css/theme.source.css. Change these tokens and the whole theme follows β
no JavaScript config involved.
Templates consume these as Tailwind utilities (font-display, text-ink, bg-alabaster,
rounded-edge, β¦), so editing a token re-flows every screen at once.
Don't edit default in place
To rebrand, create your own child theme (below) and override only the tokens you need. That keeps your changes upgrade-safe. For the full set of CSS options and module-CSS exclusion, see CSS Configuration.
Light and dark appearance¶
OBSIDIAN can offer the shopper a light, automatic or dark storefront. It ships turned off: a dark storefront is a brand decision, and catalogue photography on a white background looks very different against a dark page. Check yours before you enable it.
Enabled, a three-state control appears in the header β sun, monitor, moon β with the automatic
state in the middle. Automatic follows the operating system and keeps following it if the shopper
changes it mid-visit. The choice lives in localStorage, never in a cookie.
It never varies the served document¶
The appearance is decided in the browser, after the HTML has been delivered. Two shoppers with
opposite appearances receive the same bytes, so a page stays as cacheable as it was: no
X-Magento-Vary, no duplicated Varnish entries, no Vary header of its own.
A small inline script in the <head> β emitted through Magento's SecureHtmlRenderer, so it
carries the CSP nonce β reads the stored choice and stamps data-theme on <html> before the
first paint. The appearance tokens are inlined next to it, so the first frame is already correct
even while the deferred stylesheet is still in flight.
The automatic state needs JavaScript
The script is what translates the system preference into an appearance. With scripts disabled
the storefront stays light. That is also what makes the off switch absolute: no script, no
data-theme, no dark appearance.
The dark palette¶
The dark appearance redefines the same tokens rather than introducing new ones, so every
template that already reads text-ink or bg-alabaster follows along untouched. The palette lives
in its own file, web/css/appearance.css:
The indirection is deliberate. Token names describe the light appearance β --color-ink means
"dark ink", --color-alabaster means "pale stone" β so in the dark appearance their values say the
opposite of their names. Assigning them from role variables (--dark-text, --dark-surface) is
what keeps that readable instead of looking like a mistake.
To rebrand the dark appearance, override the role variables in your child theme; you never need to touch the mapping.
Two things to check on a dark storefront
Product photography. Catalogue images with white backgrounds become bright rectangles on a dark page. No token fixes this β decide whether to mitigate it or accept it, with the grid in front of you.
Surface separation. Contrast ratio is a text-legibility metric and compresses between dark
surfaces: two surfaces a shopper distinguishes easily can measure 1.1:1. Compare perceptual
lightness (CIELAB L*) instead β OBSIDIAN keeps adjacent surfaces at least 7 L* apart, the
same separation its light palette already uses.
Build your own theme on top¶
Create a theme under app/design/frontend/Vendor/Custom/ and inherit from theme-base (clean
slate) or default (keep OBSIDIAN and tweak):
theme-base or default?
Inherit from default when OBSIDIAN is close to what you want β retheme its tokens and
override a few templates. It's the fastest path and you keep the styled, parity-complete
storefront. Start from theme-base only when you want a clean slate and will design every
surface from zero.
-
registration.phpandtheme.xmlwith the parent of your choice: -
Opt in to the MageObsidian build with
etc/mage_obsidian_compatibility.xml: -
web/theme.config.jsβ build options (ESM). Tokens go in CSS, not here: -
web/css/theme.source.cssβ your@themetokens (and any overrides).
Then run --generate and mage-obsidian:build-themes again. Full reference:
Compatibility Configuration and
Theme Configuration.
Override templates (Twig)¶
Templates live at <Vendor>_<Module>/templates/**/*.twig. To override one, recreate the same path
in your theme β Magento's fallback resolves the most specific version. For example, the page title:
Notice the design tokens surfacing as utility classes (font-display, text-ink). For the Twig
runtime, helpers, and filters, see Twig Engine and
Helpers & Filters.
Vue islands & JavaScript¶
The default theme mounts interactive Vue islands for the dynamic bits β header search,
cart / wishlist / compare counts, the mobile menu, the store switcher, drawers, and toasts β each
hydrated lazily so the page stays fast. You extend the theme by adding or overriding components and
exposing the NPM packages you need (Pinia is exposed out of the box).
- Add components and scripts under
web/β see Creating Scripts and Components. - Learn how islands are mounted in Vue Islands.
What's included (Luma parity)¶
The theme covers the same storefront surface as Luma, rebuilt in Twig + Vue:
- Chrome: header, footer, navigation, mobile menu, store/currency switcher.
- Catalog: category listing, layered navigation, product detail page, swatches.
- Purchase: cart, checkout, instant purchase, gift messages, multishipping.
- Account: customer login & account, wishlist, compare, reviews, sales/orders.
- Search: quick search with autocomplete.
Next steps¶
-
Compatibility Themes
The full mechanism behind compatible themes: compatibility, CSS, config, and components.
-
Twig Engine
Write and override templates in Twig, with helpers and filters.
-
Getting started
Install the components and build a theme from scratch.