What this package is. marshmallow/nova-styling is a CSS-only theme for Laravel Nova (3.x era) that makes the admin panel responsive and adds a dark mode toggle on top of the "A Responsive Laravel Nova theme" base. It is archived with 0 dependents, so treat it as a starting point or a vendored asset rather than a long-lived dependency.
Minimal steps
nova.laravel.com Composer repository):composer require marshmallow/nova-styling
app/Providers/NovaServiceProvider.php — Nova 3 themes are registered in boot(), not via config/nova.php:use Laravel\Nova\Nova;
public function boot()
{
parent::boot();
Nova::theme('marshmallow/nova-styling');
}
php artisan config:clear && php artisan view:clear
/nova, confirm the responsive layout, then click the theme/dark-mode control (usually in the user menu) and reload to verify the preference persists.Where to look first
README.md for the exact Nova::theme() argument — theme paths differ between hand-rolled themes (vendor/... path) and packaged ones.vendor/marshmallow/nova-styling/resources/ and .../dist/ — if dist/ is empty or missing you have source-only and must build it yourself.NovaServiceProvider::boot() in your app — that's the single wiring point and the fastest place to disable the theme if something breaks.composer.lock / composer show marshmallow/nova-styling — read the laravel/nova version constraint before assuming it works on your Nova major.First real use case. An internal admin panel on Nova 3 with a global dark-mode option and a layout that survives on a laptop screen — install, register, toggle dark mode, then override the brand color so it matches your product.
Keep registration behind a config flag so you can kill-switch it without a deploy:
// config/nova.php (custom key) or .env: NOVA_THEME=marshmallow/nova-styling
if ($theme = config('nova.custom_theme')) {
Nova::theme($theme);
}
Nova::theme() is last-call-wins — if another package or your own provider also calls it, you'll get silent surprises. Grep for Nova::theme( in app/ and vendor/ when the styling doesn't appear.
Never edit files in vendor/. Add an override stylesheet that loads after the theme and register it with Nova::style():
Nova::style('css/nova-overrides.css'); // public/css/nova-overrides.css
Then do your work there. Useful first overrides:
/* brand + density */
:root { --nova-brand: #4f46e5; }
.btn-primary { background-color: var(--nova-brand); }
/* dark-mode-specific fixes */
.dark .card, [data-theme="dark"] .card { /* whatever the theme's hook is */ }
Inspect the DOM once to learn which hook the theme uses (.dark class, data-theme attribute, or a body class) — every downstream override depends on that one detail.
Custom Nova components are the usual casualty. Write CSS against semantic tokens, not literals:
<template>
<div class="my-card">…</div>
</template>
<style>
.my-card {
background: var(--card-bg, #fff);
color: var(--card-fg, #111827);
}
</style>
Anything with hard-coded #fff/#000 will look broken in one of the two modes. A quick visual-regression pass (Playwright screenshot of the dashboard in both modes) catches this cheaply.
nova-overrides.css, not into the theme.Ctrl+Shift+R).Nova::style() versioning, or a purge).public/css/ and register it with Nova::style(). You drop the Composer dependency, keep the look, and are free to edit. Do this the day you decide the theme is a keeper.Nova version is the whole ballgame. This is a Nova 3-style theme. Nova 4+ dropped Nova::theme() and moved to Tailwind + resources/css/nova.css overrides. If Nova::theme() silently does nothing, check your Nova major first — no amount of cache clearing will fix it. The forward migration is: take the theme's CSS, port the palette/variables into your app's nova.css, and re-implement dark mode yourself (Nova 4 has no built-in dark mode either).
Archived + 0 dependents = no upstream fixes. Pin the exact version in composer.json ("marshmallow/nova-styling": "1.2.3", not ^1.0), and vendor the CSS as soon as practical. Also expect the laravel/nova constraint to block a Nova upgrade; be ready to composer remove it during that upgrade rather than fight the constraint.
Missing dist/ assets. Some theme packages commit source but not build output. If the styles don't load, check vendor/marshmallow/nova-styling/dist/. If it's empty, cd into the package and run npm ci && npm run prod — knowing that node_modules inside vendor/ gets wiped on composer install is the reason vendoring is the better endgame.
Theme CSS selectors are an unstable API. Nova's class names change between minor versions, and this theme was written against one snapshot. Upgrades can break layout in ways that look like "the theme broke" but are really "Nova renamed a wrapper." Debug by temporarily commenting out Nova::theme() to confirm the theme is the cause, then diff the DOM.
Dark mode flash (FOUC). Preference is typically stored in localStorage and applied by JS after first paint — users see a light flash on every navigation. Mitigate with a tiny inline script in your own layout/asset that sets the class before the app boots, or accept it. Also verify the toggle survives localStorage clearing and works in a private window (it should default sensibly, not to an unstyled state).
Contrast and accessibility. Dark-mode themes commonly ship low-contrast muted text and colored badges. Run an axe/Lighthouse pass on both modes; fix in your override file rather than filing an issue against an archived repo.
Things the theme will not touch. Mail templates, PDF/export views, error pages, and Nova's 403/404 screens are outside the theme's scope. If your admin "looks half-themed," that's why.
Debugging checklist, in order: composer show the Nova version → confirm boot() runs (temporary dd() or a log line) → confirm the CSS file is actually in the page (<link> in DevTools Network) → confirm your override file is the last stylesheet → hard reload / disable cache.
Extension points worth knowing. Nova::style() (append CSS), Nova::script() (small JS for toggle persistence), Nova's brand-color config, and resources/views/vendor/nova/ publishing for layout-level markup changes. Between those four you can re-implement most of what this theme does, which is exactly the escape hatch you'll want given it's archived.
How can I help you explore Laravel packages today?