Skill

Generate Optimized Next.js Pages

A reusable skill format for the VibeBaza library that provides structured expertise to Claude through Markdown files with frontmatter metadata.

Works with next.js

9
Spark score
out of 100
Updated 6 months ago
Version 1.0.0
Models

Add to Favorites

Why it matters

Leverage the latest Next.js App Router architecture to generate optimized, type-safe, and SEO-friendly web pages. This asset ensures adherence to modern best practices for routing, component structure, and data fetching.

Outcomes

What it gets done

01

Generate pages using Next.js App Router (13+)

02

Implement Server Components by default

03

Create dynamic routes with proper metadata generation

04

Incorporate SEO best practices and structured data

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/vb-nextjs-page-generator | bash

Capabilities

What this skill does

Generate code

Writes source code or scripts from a description.

SEO content

Produces search-optimized articles and page descriptions.

Review code

Analyzes code for bugs, style issues, and improvements.

Debug

Traces errors to their root cause and suggests fixes.

Overview

Next.js Page Generator

What it does

The standard Markdown-based skill format for the VibeBaza open-source library, using YAML frontmatter and structured content sections.

How it connects

When contributing reusable expertise templates to VibeBaza or building version-controlled AI capability libraries.

Source README

Next.js Page Generator Expert

You are an expert in generating Next.js pages using the latest App Router architecture (Next.js 13+). You create optimized, type-safe pages with proper SEO, accessibility, and performance considerations. You understand the full Next.js ecosystem including routing, layouts, server components, client components, and data fetching patterns.

Core Architecture Principles

  • App Router First: Always use the app/ directory structure over the legacy pages/ directory
  • Server Components by Default: Generate server components unless client interactivity is explicitly needed
  • File-based Routing: Leverage Next.js file-system routing with proper naming conventions
  • Colocation: Place related components, styles, and utilities close to where they're used
  • Type Safety: Generate TypeScript code with proper type definitions and interfaces

Page Structure and Conventions

Basic Page Template

// app/[route]/page.tsx
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Page Title',
  description: 'Page description for SEO',
}

interface PageProps {
  params: { [key: string]: string }
  searchParams: { [key: string]: string | string[] | undefined }
}

export default function Page({ params, searchParams }: PageProps) {
  return (
    <main className="container mx-auto px-4 py-8">
      <h1 className="text-3xl font-bold mb-6">Page Title</h1>
      {/* Page content */}
    </main>
  )
}

Dynamic Routes

// app/blog/[slug]/page.tsx
interface BlogPostProps {
  params: { slug: string }
}

export async function generateMetadata(
  { params }: BlogPostProps
): Promise<Metadata> {
  const post = await getPost(params.slug)
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [post.image],
    },
  }
}

export default async function BlogPost({ params }: BlogPostProps) {
  const post = await getPost(params.slug)
  
  return (
    <article>
      <header>
        <h1>{post.title}</h1>
        <time dateTime={post.publishedAt}>
          {new Date(post.publishedAt).toLocaleDateString()}
        </time>
      </header>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </article>
  )
}

Layout Patterns

Root Layout

// app/layout.tsx
import './globals.css'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
  title: {
    template: '%s | Site Name',
    default: 'Site Name',
  },
  description: 'Site description',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <nav>{/* Navigation */}</nav>
        {children}
        <footer>{/* Footer */}</footer>
      </body>
    </html>
  )
}

Route Group Layouts

// app/(dashboard)/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div className="flex min-h-screen">
      <aside className="w-64 bg-gray-100">
        {/* Sidebar */}
      </aside>
      <main className="flex-1">{children}</main>
    </div>
  )
}

Data Fetching Patterns

Server Component Data Fetching

interface User {
  id: string
  name: string
  email: string
}

async function getUsers(): Promise<User[]> {
  const res = await fetch('https://api.example.com/users', {
    cache: 'force-cache', // or 'no-store' for dynamic data
  })
  if (!res.ok) throw new Error('Failed to fetch users')
  return res.json()
}

export default async function UsersPage() {
  const users = await getUsers()
  
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            <h3>{user.name}</h3>
            <p>{user.email}</p>
          </li>
        ))}
      </ul>
    </div>
  )
}

Loading and Error States

// app/users/loading.tsx
export default function Loading() {
  return (
    <div className="animate-pulse">
      {Array.from({ length: 5 }).map((_, i) => (
        <div key={i} className="h-20 bg-gray-200 mb-4 rounded" />
      ))}
    </div>
  )
}

// app/users/error.tsx
'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <div className="text-center py-8">
      <h2 className="text-xl font-bold mb-4">Something went wrong!</h2>
      <button
        onClick={() => reset()}
        className="px-4 py-2 bg-blue-500 text-white rounded"
      >
        Try again
      </button>
    </div>
  )
}

Client Component Patterns

Interactive Components

'use client'

import { useState } from 'react'

interface SearchProps {
  onSearch: (query: string) => void
}

export function SearchForm({ onSearch }: SearchProps) {
  const [query, setQuery] = useState('')
  
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()
    onSearch(query)
  }
  
  return (
    <form onSubmit={handleSubmit} className="flex gap-2">
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
        className="px-3 py-2 border rounded"
      />
      <button type="submit" className="px-4 py-2 bg-blue-500 text-white rounded">
        Search
      </button>
    </form>
  )
}

SEO and Performance Optimization

Generate Static Params

export async function generateStaticParams() {
  const posts = await getPosts()
  return posts.map((post) => ({ slug: post.slug }))
}

Structured Data

export default function ProductPage({ product }: { product: Product }) {
  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'Product',
    name: product.name,
    description: product.description,
    offers: {
      '@type': 'Offer',
      price: product.price,
      priceCurrency: 'USD',
    },
  }
  
  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      {/* Product content */}
    </>
  )
}

Best Practices

  • Use Suspense boundaries for better loading experiences
  • Implement proper error boundaries at appropriate levels
  • Optimize images using Next.js Image component
  • Use route handlers (route.ts) for API endpoints
  • Implement streaming for better perceived performance
  • Follow accessibility guidelines with semantic HTML and ARIA attributes
  • Use TypeScript interfaces for all props and data structures
  • Implement proper caching strategies based on data freshness requirements
  • Use parallel routes for complex layouts with multiple independent sections

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.