Layouts and Pages
Create beautiful layouts and pages in VitNode plugins using Next.js App Router patterns.
Building layouts and pages in VitNode is just like Next.js - if you know Next.js, you're already a VitNode pro! Think of pages as rooms and layouts as the house structure that holds everything together.
VitNode automatically copies files from your plugin's app
directory to the
main application. No extra setup needed!
Creating Pages
Pages are React components that live in page.tsx
files. Each page represents a unique URL route.
Basic Page
export default function BlogHomePage() {
return (
<div className="py-12 text-center">
<h1 className="mb-4 text-4xl font-bold">Welcome to Our Blog! 🚀</h1>
<p className="text-gray-600">Where awesome content lives</p>
</div>
);
}
Nested Routes
Create folders to organize your routes:
export default function DashboardPage() {
return (
<div>
<h1 className="text-3xl font-bold">Dashboard</h1>
<p>Manage your blog content here</p>
</div>
);
}
This creates /dashboard
route.
Dynamic Routes
Use [param]
for dynamic URLs:
interface PostPageProps {
params: Promise<{ slug: string }>;
}
export default async function PostPage({ params }: PostPageProps) {
const { slug } = await params;
return (
<div>
<h1>Post: {slug}</h1>
<p>Your post content goes here</p>
</div>
);
}
Creating Layouts
Layouts wrap your pages and provide shared UI elements like headers, navigation, and footers.
Basic Layout
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'My Blog Plugin',
description: 'A fantastic blog plugin for VitNode',
};
export default function BlogLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="min-h-screen">
<header className="border-b bg-white shadow-sm">
<div className="container mx-auto px-4 py-4">
<h1 className="text-2xl font-bold text-indigo-600">✨ My Blog</h1>
</div>
</header>
<main className="container mx-auto px-4 py-8">{children}</main>
<footer className="bg-gray-900 py-8 text-white">
<div className="container mx-auto px-4 text-center">
<p>Made with ❤️ using VitNode</p>
</div>
</footer>
</div>
);
}
Nested Layout for Specific Sections
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex">
{/* Sidebar */}
<aside className="min-h-screen w-64 border-r bg-gray-50">
<nav className="p-6">
<h2 className="mb-4 font-semibold">Dashboard</h2>
<ul className="space-y-2">
<li>
<a
href="/dashboard"
className="text-gray-700 hover:text-indigo-600"
>
Overview
</a>
</li>
<li>
<a
href="/dashboard/posts"
className="text-gray-700 hover:text-indigo-600"
>
Posts
</a>
</li>
<li>
<a
href="/dashboard/settings"
className="text-gray-700 hover:text-indigo-600"
>
Settings
</a>
</li>
</ul>
</nav>
</aside>
{/* Main content */}
<div className="flex-1 p-8">{children}</div>
</div>
);
}
Adding Metadata
Improve SEO and social sharing with metadata:
import { Metadata } from 'next';
interface PostPageProps {
params: Promise<{ slug: string }>;
}
export async function generateMetadata({
params,
}: PostPageProps): Promise<Metadata> {
const { slug } = await params;
return {
title: `Post: ${slug}`,
description: `Read about ${slug} on our blog`,
};
}
export default async function PostPage({ params }: PostPageProps) {
const { slug } = await params;
return (
<article>
<h1>Post: {slug}</h1>
<p>Your post content here...</p>
</article>
);
}