Adding Pages
Create a new route that fits the existing layout.
DirectoryKit uses Next.js route groups (folders in parentheses) to apply shared layouts. Adding a new page = adding one page.tsx file under the right group.
Pick the right route group
| Group | Layout | Use for |
|---|---|---|
(marketing)/ | Header + Footer + AdBanner | Public pages — blog, pricing, FAQ, about |
(dashboard)/ | Header + user dashboard layout | Logged-in user pages |
(admin)/admin/ | Admin sidebar layout | Admin-only pages |
The parentheses in the folder name are stripped from the URL — they only exist to group by layout.
Example: add a public /roadmap page
1. Create the file
app/(marketing)/roadmap/page.tsx
2. Write the component
import type { Metadata } from 'next';
import { siteConfig } from '@/config/site.config';
export const metadata: Metadata = {
title: `Roadmap — ${siteConfig.name}`,
description: 'What we are building next.',
};
export default function RoadmapPage() {
return (
<div className="mx-auto max-w-3xl px-6 py-16">
<h1 className="text-4xl font-bold">Roadmap</h1>
<p className="mt-4 text-muted-foreground">
Features we're working on.
</p>
<ul className="mt-8 space-y-4">
<li>Q2: AI-powered search</li>
<li>Q3: Mobile app</li>
</ul>
</div>
);
}3. Add a nav link (optional)
If you want the page in the header or footer, edit components/layout/Header.tsx or components/layout/Footer.tsx and add your entry to the nav array.
Example: add a logged-in /invites page
1. Create the file
app/(dashboard)/invites/page.tsx
2. Protect it
import { requireAuth, getCurrentUser } from '@/lib/supabase/auth-helpers';
export default async function InvitesPage() {
const redirect = await requireAuth();
if (redirect) return redirect;
const user = await getCurrentUser();
return (
<div>
<h1>Your invites, {user!.email}</h1>
</div>
);
}Example: add an admin page
1. Create the file
app/(admin)/admin/reports/page.tsx
2. Protect it
import { isAdmin, requireAuth } from '@/lib/supabase/auth-helpers';
import { notFound } from 'next/navigation';
export default async function AdminReportsPage() {
const redirect = await requireAuth();
if (redirect) return redirect;
if (!(await isAdmin())) notFound();
return <div>Admin reports...</div>;
}Appears at /admin/reports. Won't show up for non-admins.
Pages that need data
Use the db helper for server-side data fetching:
import { db } from '@/lib/supabase/database';
export default async function LiveAppsPage() {
const apps = await db.find('apps',
{ status: 'live' },
{ sort: { upvotes: -1 }, limit: 20 }
);
return (
<ul>
{apps.map((app) => <li key={app.id}>{app.name}</li>)}
</ul>
);
}Adding an API route
If your page needs data mutations, pair it with an API route at app/api/your-thing/route.ts — see API Reference Overview for the template.
Docs page (this site)
If you want a new page in this documentation:
- Create
content/docs/<section>/<page>.mdxwith frontmatter - Add an entry to
lib/docs/navigation.ts
With AI
Add a new page at route
\{/your-url-path\}to this DirectoryKit project.Details:
- Purpose: {what the page is for — e.g. "a public roadmap", "a logged-in invites page", "an admin reports page"}
- Access: {public | logged-in-only | admin-only}
- Content sections: {list what the page shows — e.g. "a hero, a 3-column feature grid, a FAQ"}
- Data source: {static content | Supabase table "X" via db.find | Stripe API | none}
Follow CLAUDE.md conventions:
- Pick the right route group ((marketing) / (dashboard) / (admin)).
- Use @/ alias for imports.
- Use siteConfig for brand name in metadata.
- For protected pages, use
requireAuth()/isAdmin()from @/lib/supabase/auth-helpers. - For DB queries, use the
dbsingleton from @/lib/supabase/database. - Use shadcn/ui components from @/components/ui, not raw HTML.
Also add a nav link if appropriate (Header.tsx or Footer.tsx).