next-js/skills/skills/page-scaffold/SKILL.md
Create new Next.js pages following the project's Pages Router conventions, including public-facing pages with SEO, admin-protected pages with auth, and dynamic routes. Use this skill whenever the user wants to add a new route, create a new page, add a public page, create an admin page, add a landing page, or set up a new URL endpoint. Trigger on: "new page", "add route", "create page", "landing page", "add a page at /...", or when the user describes any new URL that needs to exist in the application.
npx skillsauth add spuneiartur/claude-agent-specs page-scaffoldInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create new Next.js pages using the project's Pages Router conventions. The project uses the pages/ directory (not App Router) with specific patterns for public pages, admin pages, and dynamic routes.
For pages accessible without authentication. Uses PresentationLayout (header + footer) and NextSeo for SEO.
import { NextSeo } from 'next-seo';
import { PresentationLayout } from '@components';
const Page = ({ data }) => {
return (
<PresentationLayout>
<NextSeo
title="Page Title — Site Name"
description="Page description for search engines"
openGraph={{
title: 'Page Title',
description: 'Page description',
// images: [{ url: '/images/og-image.jpg', width: 1200, height: 630 }],
}}
/>
{/* Page content */}
<section className="py-16">
<div className="container mx-auto px-4">
<h1 className="text-4xl font-bold text-gray-900">Page Title</h1>
</div>
</section>
</PresentationLayout>
);
};
// Optional: server-side data fetching
export async function getServerSideProps() {
try {
// const data = await publicApi.getData();
return { props: { /* data */ } };
} catch {
return { props: {} };
}
}
export default Page;
For pages requiring authentication. Uses Layout (admin sidebar + header) with checkAuth/withAuth.
import { checkAuth, withAuth } from '@auth';
import { Layout } from '@components';
const Page = () => {
return (
<Layout title="Page Title">
{/* Admin page content */}
</Layout>
);
};
export async function getServerSideProps(context) {
return await checkAuth(context);
}
export default withAuth(Page);
For pages with URL parameters. Use [param].js file naming.
Public dynamic route (e.g., /blog/[slug].js):
import { NextSeo } from 'next-seo';
import { PresentationLayout } from '@components';
const Page = ({ item }) => (
<PresentationLayout>
<NextSeo title={item?.title} description={item?.description} />
{/* Render item */}
</PresentationLayout>
);
export async function getServerSideProps({ params }) {
try {
const item = await publicApi.getBySlug(params.slug);
if (!item) return { notFound: true };
return { props: { item } };
} catch {
return { notFound: true };
}
}
export default Page;
Admin dynamic route (e.g., /admin/resources/edit/[id].js):
import { checkAuth, withAuth } from '@auth';
import { Button, Layout } from '@components';
import { EditResourceForm } from '@components/Forms';
import { useQuery } from '@hooks';
import { useRouter } from 'next/router';
const Page = () => {
const router = useRouter();
const { id } = router.query;
const { data: resource, status } = useQuery(`admin/resources/${id}`);
return (
<Layout title="Edit Resource">
{status === 'loading' && <div>Loading...</div>}
{status === 'error' && <div>Error loading resource.</div>}
{status === 'success' && (
<>
<Button onClick={() => router.back()} className="text-yellow-600 hover:text-yellow-700 text-sm font-medium mb-4">
← Back
</Button>
<EditResourceForm resource={resource} />
</>
)}
</Layout>
);
};
export async function getServerSideProps(context) {
return await checkAuth(context);
}
export default withAuth(Page);
| Pattern | File Path | URL |
|---------|-----------|-----|
| Static page | pages/about.js | /about |
| Index in folder | pages/blog/index.js | /blog |
| Dynamic param | pages/blog/[slug].js | /blog/my-post |
| Nested dynamic | pages/admin/articles/edit/[id].js | /admin/articles/edit/abc123 |
forgot-password.js)index.js inside directories for clean URLs (e.g., pages/admin/articles/add/index.js → /admin/articles/add)| Layout | Use For | Provides |
|--------|---------|----------|
| PresentationLayout | Public/visitor pages | Header + Footer + mobile menu |
| Layout | Admin pages | Admin sidebar + header + title prop |
Import both from @components.
Use next-seo package for per-page SEO:
import { NextSeo } from 'next-seo';
<NextSeo
title="Page Title"
description="Meta description"
canonical="https://example.com/page"
openGraph={{
title: 'OG Title',
description: 'OG Description',
images: [{ url: '/images/og.jpg', width: 1200, height: 630, alt: 'Image description' }],
}}
/>
The project also has a custom OpenGraph component in @components for more control.
The authentication flow for admin pages uses two layers:
getServerSideProps): checkAuth(context) validates the JWT token from cookies. Redirects to /login if invalid.withAuth HOC): Monitors token expiry, triggers refresh on window focus, redirects on auth failure.Always use both together for admin pages.
| What | Import From |
|------|------------|
| PresentationLayout, Layout, Button | @components |
| checkAuth, withAuth | @auth |
| useQuery, useInfiniteQuery | @hooks |
| NextSeo | next-seo |
| useRouter | next/router |
tools
Replace with description of the skill and when Claude should use it.
tools
Comprehensive website performance audit and optimization skill. Identifies and automatically fixes performance issues including image optimization, video compression, lazy loading, Core Web Vitals, bundle size, and rendering strategy. Uses Lighthouse (via CLI or MCP when available), ffmpeg for media processing, and the project's existing Image component with blur-up lazy loading. Use this skill whenever the user mentions: website speed, page load time, performance audit, Core Web Vitals, Lighthouse, optimize images, compress videos, lazy loading, LCP, CLS, FID, INP, slow website, speed up, performance optimization, image compression, video optimization, blur placeholder, WebP conversion, media audit, bundle size, or wants to improve their website's loading performance. Also trigger when the user says "my site is slow", "optimize for speed", "reduce load time", "improve performance", or asks about image/video optimization in any context.
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
tools
Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.