Explore

Troubleshooting

The problems developers hit in their first day with Nova — and the fixes.

If your problem isn't here, open a GitHub discussion. Every second report ends up in this file.

Styles look unstyled or off-brand

Diagnose · Tailwind isn't seeing Nova's source files, or the token layer isn't imported.

tsx
/* app/styles.css */
@import "tailwindcss";
@import "@novix-ui/react/tokens.css";

Flash of wrong theme on load (FOUT/FOUC)

Diagnose · The theme class is applied in a React effect, so the first paint uses the default.

tsx
// Inject before hydration (root layout head)
<script dangerouslySetInnerHTML={{ __html:
`(() => { const t = localStorage.getItem('nova-theme') || 'system';
const d = t === 'system' ? matchMedia('(prefers-color-scheme: dark)').matches : t === 'dark';
document.documentElement.dataset.theme = d ? 'dark' : 'light'; })();` }} />

Hydration mismatch warnings

Diagnose · A component reads window/localStorage during SSR and renders different HTML on the client.

tsx
import { useEffect, useState } from "react";
 
function useHydrated() {
const [h, setH] = useState(false);
useEffect(() => setH(true), []);
return h;
}

Focus ring is missing or invisible

Diagnose · Global CSS is suppressing :focus-visible, or a wrapper element captures focus.

tsx
/* Remove any global reset like: */
button:focus { outline: none; }
 
/* Nova relies on :focus-visible for two-layer rings. */

Icons render at the wrong size

Diagnose · Passing width/height directly instead of using Nova's <Icon size='…' /> wrapper.

tsx
import { Icon } from "@novix-ui/react";
import { Search } from "lucide-react";
 
<Icon size="sm" as={Search} label="Search" />

asChild throws 'React.Children.only expected'

Diagnose · asChild renders onto a child but expects exactly one child element.

tsx
// Wrong — two children
<Button asChild><Link to="/x">Go</Link><span>!</span></Button>
 
// Right — single child
<Button asChild><Link to="/x">Go!</Link></Button>

Bundle size is larger than expected

Diagnose · Barrel imports pull in every component, defeating tree-shaking.

tsx
// Prefer named imports the bundler can shake
import { Button, Card } from "@novix-ui/react";
 
// Avoid
import * as Nova from "@novix-ui/react";