Introduction to NextJS Layouts
If you’re new to NextJS, you might be wondering what “NextJS Layout” are. Think of a layout like a template that wraps around your pages. It’s like having a consistent frame for all your photos – the frame stays the same, but the picture inside changes!
For example, if your website has a header and footer that appear on every page, you’d put those in a layout. The main content in the middle changes for each page, but the header and footer stay consistent.
Getting Started: Basic NextJS Layout Setup
First, let’s make sure you have NextJS installed. Open your terminal and run:
npx create-next-app@latest my-app
cd my-app
npm run dev
This creates a new NextJS project and starts the development server. You should see your app at http://localhost:3000
Understanding the Basic Folder Structure
When you open your new NextJS project, you’ll see these main folders:
my-app/
├── app/ # This is where your pages and layouts live
├── public/ # Images and static files
├── node_modules/ # Don't touch this - it's automatic!
└── package.json # Project settings and dependencies
Inside the app folder, you’ll find:
layout.tsx– The main template for your entire apppage.tsx– Your home pageglobals.css– Your styles
Your First Layout
Let’s look at the basic layout file that NextJS creates for you. Open app/layout.tsx:
// This is your main layout - it wraps around EVERY page
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{/* This is where your page content goes */}
{children}
</body>
</html>
)
}
This is the simplest possible layout. The children part gets replaced with whatever page you’re currently viewing.
Let’s Make a Real Layout
Let’s create a more useful layout with a header and footer:
// app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{/* Header that shows on every page */}
<header style={{
backgroundColor: 'blue',
color: 'white',
padding: '1rem',
textAlign: 'center'
}}>
<h1>My Awesome Website</h1>
<nav>
<a href="/" style={{ color: 'white', margin: '0 1rem' }}>Home</a>
<a href="/about" style={{ color: 'white', margin: '0 1rem' }}>About</a>
<a href="/contact" style={{ color: 'white', margin: '0 1rem' }}>Contact</a>
</nav>
</header>
{/* Main content area - changes for each page */}
<main style={{ padding: '2rem' }}>
{children}
</main>
{/* Footer that shows on every page */}
<footer style={{
backgroundColor: 'gray',
color: 'white',
padding: '1rem',
textAlign: 'center'
}}>
<p>© 2024 My Website. All rights reserved.</p>
</footer>
</body>
</html>
)
}
Now every page on your website will have this same header and footer! The {children} part is where each page’s unique content goes.
Creating Different User Sections
Now let’s say you’re building an app that has:
- Public pages (home, about, contact)
- User dashboard (after login)
- Admin area (for website managers)
Here’s how you’d organize this in NextJS:
Step 1: Create the Folder Structure
In your app folder, create these folders:
app/
├── (public)/
│ ├── page.tsx # Home page
│ ├── about/
│ │ └── page.tsx # About page
│ └── contact/
│ └── page.tsx # Contact page
├── dashboard/
│ └── page.tsx # User dashboard
├── admin/
│ └── page.tsx # Admin area
└── layout.tsx # Root layout
The parentheses around (public) tell NextJS “this is just for organization, don’t put it in the URL.” So the about page will be at /about, not /public/about.
Step 2: Create the Public Pages
Home page (app/(public)/page.tsx):
export default function Home() {
return (
<div>
<h1>Welcome to Our Website!</h1>
<p>This is the public home page that anyone can see.</p>
<div style={{
backgroundColor: 'lightblue',
padding: '2rem',
margin: '1rem 0'
}}>
<h2>Public Content</h2>
<p>This content is for everyone - no login required!</p>
</div>
</div>
)
}About page (app/(public)/about/page.tsx):
export default function About() {
return (
<div>
<h1>About Us</h1>
<p>Learn more about our company and mission.</p>
<p>This is another public page that anyone can access.</p>
</div>
)
}Step 3: Create User-Specific Layouts
Now let’s make different layouts for different types of users. We’ll create separate layout files for each section.
User Dashboard Layout (app/dashboard/layout.tsx):
// This layout only applies to pages in the /dashboard folder
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div style={{
display: 'flex',
minHeight: '100vh',
backgroundColor: '#f5f5f5'
}}>
{/* Sidebar navigation */}
<aside style={{
width: '250px',
backgroundColor: 'white',
padding: '2rem',
boxShadow: '2px 0 5px rgba(0,0,0,0.1)'
}}>
<h2>User Dashboard</h2>
<nav style={{ display: 'flex', flexDirection: 'column' }}>
<a href="/dashboard" style={{ padding: '0.5rem 0' }}>Overview</a>
<a href="/dashboard/profile" style={{ padding: '0.5rem 0' }}>Profile</a>
<a href="/dashboard/settings" style={{ padding: '0.5rem 0' }}>Settings</a>
<a href="/" style={{ padding: '0.5rem 0', color: 'blue' }}>← Back to Site</a>
</nav>
</aside>
{/* Main content area */}
<main style={{
flex: 1,
padding: '2rem'
}}>
<div style={{
backgroundColor: 'white',
padding: '2rem',
borderRadius: '8px',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
}}>
{children}
</div>
</main>
</div>
)
}
User Dashboard Page (app/dashboard/page.tsx):
export default function Dashboard() {
return (
<div>
<h1>Welcome to Your Dashboard!</h1>
<p>This is where regular users can manage their account.</p>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
gap: '1rem',
marginTop: '2rem'
}}>
<div style={{
backgroundColor: '#e3f2fd',
padding: '1.5rem',
borderRadius: '8px'
}}>
<h3>Your Profile</h3>
<p>View and edit your personal information</p>
</div>
<div style={{
backgroundColor: '#f3e5f5',
padding: '1.5rem',
borderRadius: '8px'
}}>
<h3>Settings</h3>
<p>Customize your preferences</p>
</div>
</div>
</div>
)
}Admin Layout (app/admin/layout.tsx):
// This layout only applies to pages in the /admin folder
export default function AdminLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div style={{
display: 'flex',
minHeight: '100vh',
backgroundColor: '#1a1a1a',
color: 'white'
}}>
{/* Admin sidebar */}
<aside style={{
width: '300px',
backgroundColor: '#2d2d2d',
padding: '2rem'
}}>
<h2 style={{ color: 'red' }}>Admin Panel</h2>
<p style={{ fontSize: '0.9rem', color: '#ccc' }}>
Restricted Area - Authorized Personnel Only
</p>
<nav style={{ display: 'flex', flexDirection: 'column', marginTop: '2rem' }}>
<a href="/admin" style={{ padding: '0.75rem 0', color: 'white' }}>Admin Home</a>
<a href="/admin/users" style={{ padding: '0.75rem 0', color: 'white' }}>Manage Users</a>
<a href="/admin/settings" style={{ padding: '0.75rem 0', color: 'white' }}>System Settings</a>
<a href="/" style={{ padding: '0.75rem 0', color: 'lightblue' }}>← Back to Main Site</a>
</nav>
</aside>
{/* Admin main content */}
<main style={{
flex: 1,
padding: '2rem'
}}>
<div style={{
backgroundColor: '#2d2d2d',
padding: '2rem',
borderRadius: '8px'
}}>
{children}
</div>
</main>
</div>
)
}
Admin Page (app/admin/page.tsx):
export default function Admin() {
return (
<div>
<h1>Administrator Control Panel</h1>
<p style={{ color: '#ff6b6b' }}>
⚠️ Warning: This area contains sensitive system controls
</p>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
gap: '1rem',
marginTop: '2rem'
}}>
<div style={{
backgroundColor: '#ffebee',
padding: '1.5rem',
borderRadius: '8px',
color: 'black'
}}>
<h3>User Management</h3>
<p>Create, edit, and delete user accounts</p>
</div>
<div style={{
backgroundColor: '#e8f5e8',
padding: '1.5rem',
borderRadius: '8px',
color: 'black'
}}>
<h3>System Analytics</h3>
<p>View website statistics and reports</p>
</div>
<div style={{
backgroundColor: '#fff3e0',
padding: '1.5rem',
borderRadius: '8px',
color: 'black'
}}>
<h3>Database Tools</h3>
<p>Manage and backup your data</p>
</div>
</div>
</div>
)
}How Layouts Work Together
Here’s the magic of NextJS layouts:
- Root Layout (
app/layout.tsx) – Applies to EVERY page - Section Layout (like
app/dashboard/layout.tsx) – Applies only to pages in that folder - Page (like
app/dashboard/page.tsx) – The actual page content
NextJS automatically nests these layouts. So when you visit /dashboard, you get:
Root Layout (header/footer)
└── Dashboard Layout (sidebar)
└── Dashboard Page (main content)
Testing Your Setup
Now you should have these pages working:
http://localhost:3000– Public home pagehttp://localhost:3000/about– Public about pagehttp://localhost:3000/dashboard– User dashboardhttp://localhost:3000/admin– Admin area
Each section has its own look and feel, but they all share the root layout’s header and footer!
Adding More Pages to Each Section
Want to add more pages? Just create new folders and page.tsx files:
Add user profile page (app/dashboard/profile/page.tsx):
export default function Profile() {
return (
<div>
<h1>Your Profile</h1>
<p>This is where users can edit their profile information.</p>
<form style={{ marginTop: '2rem' }}>
<div style={{ marginBottom: '1rem' }}>
<label>Name:</label>
<input type="text" style={{ display: 'block', marginTop: '0.5rem', padding: '0.5rem' }} />
</div>
<div style={{ marginBottom: '1rem' }}>
<label>Email:</label>
<input type="email" style={{ display: 'block', marginTop: '0.5rem', padding: '0.5rem' }} />
</div>
<button type="submit" style={{
backgroundColor: 'blue',
color: 'white',
padding: '0.75rem 1.5rem',
border: 'none',
borderRadius: '4px'
}}>
Save Changes
</button>
</form>
</div>
)
}Now you can visit /dashboard/profile and it will automatically use the dashboard layout!
Understanding the File Naming
Remember these special file names:
layout.tsx– Creates a layout for that folder and all subfolderspage.tsx– Creates a page that people can visitloading.tsx– Shows loading animation (advanced)error.tsx– Shows error messages (advanced)
Tips for Beginners
- Start Simple: Don’t try to build everything at once. Start with the basic layout and add sections gradually.
- Use the Development Server: Keep
npm run devrunning while you work. It automatically updates your browser when you save files. - Check Your URLs: If a page isn’t working, make sure:
- The folder structure matches the URL you want
- You have a
page.tsxfile in that folder - There are no typos in your file names
- Layouts are Optional: You don’t need a layout for every folder. Only create them when you need different designs for different sections.
Common Questions
Q: Can I have multiple layouts?
A: Yes! Each folder can have its own layout.tsx that only applies to pages in that folder.
Q: What if I don’t want the root layout?
A: You can’t remove the root layout, but you can make it very basic.
Q: How do I add CSS styling?
A: You can use regular CSS files, or style with JavaScript objects like in the examples above.
Next Steps
Now that you have the basic structure, you can:
- Add more pages to each section
- Style your layouts with CSS instead of inline styles
- Add interactive features with React components
- Connect to a database to show real user data
Remember, the key concept is: layouts wrap pages, and they automatically nest based on your folder structure. This makes it easy to create different experiences for different types of users while keeping your code organized!
Practice by creating more pages and experimenting with different layouts. Happy coding!
