Mantine AppShell Layout — Debugging Blank Column
A systematic checklist for diagnosing and fixing unexpected blank space on the left side of a Mantine AppShell layout.
Why / When to Use
When a blank white column appears between the icon rail and page content. Usually caused by AppShell reserving navbar space that doesn’t match actual rendered content.
Core Concept / Commands
Diagnostic — count root AppShell instances
grep -rn "AppShell" src --include="*.tsx" | grep -v "AppShell\."Only ONE root <AppShell> should exist. Multiple instances create stacked reserved space.
Diagnostic — find hardcoded left offsets
grep -rn "marginLeft\|paddingLeft\|margin-left\|padding-left" \
src/app src/components --include="*.tsx" --include="*.css" --include="*.module.css"Key Options / Variants
Cause A — Navbar reserved but empty or missing
<AppShell navbar={{ width: N }}> reserves N pixels but <AppShell.Navbar> is not rendered or is empty.
Fix: remove the navbar prop, or render content inside <AppShell.Navbar>, or set navbar={{ width: 0, breakpoint: 'sm' }}.
Cause B — Double AppShell stacking
Root layout AND a route-group layout both declare <AppShell>. Both reserve space, causing combined blank offset.
Fix: remove the inner AppShell. Page-level sidebars belong inside AppShell.Main as a flex row:
<Group h="100%" gap={0} align="stretch">
<NavSidebar />
<Box flex={1}>{children}</Box>
{selectedItem && <DetailPanel />}
</Group>Cause C — Icon rail outside AppShell + AppShell also has navbar prop
Icon rail sits as a sibling outside <AppShell> while AppShell also has navbar={{ width: N }} — double left offset.
Option 1 — Move icon rail inside AppShell:
<AppShell navbar={{ width: 52, breakpoint: 'sm' }}>
<AppShell.Navbar withBorder={false}>
<IconRail />
</AppShell.Navbar>
...
</AppShell>Option 2 — Keep icon rail outside, remove navbar from AppShell:
<Group h="100vh" gap={0} align="stretch">
<IconRail /> {/* 52px, flex-shrink: 0 */}
<AppShell /* NO navbar prop */>
...
</AppShell>
</Group>Cause D — Hardcoded CSS offset
A global wrapper has marginLeft or paddingLeft compensating for something. Remove it and fix the root cause.
Cause E — Navbar width mismatch
navbar={{ width: N }} doesn’t match the actual rendered sidebar width. Set N to exactly match.
Gotchas
- The icon rail is typically 52px; set
navbar={{ width: 52 }}to match exactly. - Always run
npx tsc --noEmitafter layout changes to catch type errors. - Route group layouts (
(group)/layout.tsx) are easy to miss when auditing AppShell instances.
Source
Conversation “Web-Todo App” — 2026-05-31