スキル一覧に戻る
naopoyo

page-style

by naopoyo

Next.jsで構築したブログサイトのリポジトリです。

1🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: page-style description: page.tsx のコーディングスタイルガイド

page.tsx コーディングスタイルガイド

src/app 以下の page.tsx ファイルを作成・編集する際のスタイルガイドです。

ファイル構造

以下の順序で記述してください:

  1. import 文
  2. 定数(title, description)
  3. metadata エクスポート
  4. Props 型定義(必要な場合)
  5. dynamic / revalidate 設定
  6. generateMetadata 関数(動的メタデータの場合)
  7. デフォルトエクスポート関数

import 文

順序

  1. Next.js のモジュール(next, next/*
  2. React のモジュール(react
  3. 空行
  4. 内部モジュール(@/ から始まるパス)

同一モジュールからのインポート

同一モジュールからは1行でまとめてインポートしてください。

// Good
import { Container, PageHeader } from '@/components/layout'

// Bad
import { Container } from '@/components/layout'
import { PageHeader } from '@/components/layout'

定数定義

静的ページでは titledescription を定数として定義してください。

const title = 'About'
const description = 'naopoyo.comについて説明しているページです。'

metadata エクスポート

定数を使用して定義してください。

export const metadata: Metadata = {
  title: title,
  description: description,
}

Props 型定義

  • export type を使用してください
// Good
export type DocsPageProps = {
  searchParams: Promise<{ keyword?: string }>
}

// Bad
interface DocsPageProps {
  searchParams: Promise<{ keyword?: string }>
}

// Bad
type DocsPageProps = {
  searchParams: Promise<{ keyword?: string }>
}

dynamic / revalidate 設定

基本的にすべてのページで設定してください。

export const dynamic = 'force-static'
export const revalidate = 60

関数名

XxxPage 形式で命名してください。ディレクトリ名を PascalCase に変換して Page を付けます。

パス関数名
src/app/page.tsxHomePage
src/app/about/page.tsxAboutPage
src/app/docs/page.tsxDocsPage
src/app/docs/[documentSlug]/page.tsxDocumentPage
src/app/tools/random-emoji/page.tsxRandomEmojiPage

JSX 構造

Container

すべてのページは Container コンポーネントでラップしてください。

<Container className="flex flex-col items-center gap-8 pt-16">{/* コンテンツ */}</Container>

ホームページ以外は PageHeader コンポーネントを使用してください。

<PageHeader title={title} description={description} />

テンプレート

静的ページ(シンプル)

import { Metadata } from 'next'

import { Container, PageHeader } from '@/components/layout'

const title = 'About'
const description = 'ページの説明文です。'

export const metadata: Metadata = {
  title: title,
  description: description,
}

export const dynamic = 'force-static'
export const revalidate = 60

export default async function AboutPage() {
  return (
    <Container className="flex flex-col items-center gap-8 pt-16">
      <PageHeader title={title} description={description} />
      {/* コンテンツ */}
    </Container>
  )
}

動的ページ(パラメータあり)

import { Metadata } from 'next'
import { notFound } from 'next/navigation'

import { Container, PageHeader } from '@/components/layout'
import { client } from '@/lib/hackersheet'

export type TagPageProps = {
  params: Promise<{ tagName: string }>
}

export const dynamic = 'force-static'
export const revalidate = 60

export async function generateMetadata(props: TagPageProps): Promise<Metadata> {
  const params = await props.params
  const { tagName } = params

  // データ取得とメタデータ生成
  return {
    title: `${tagName} - Tags`,
  }
}

export default async function TagPage(props: TagPageProps) {
  const params = await props.params
  const { tagName } = params

  // データ取得
  // if (!data) return notFound()

  return (
    <Container className="flex flex-col items-center gap-8 pt-16">
      <PageHeader title={tagName} />
      {/* コンテンツ */}
    </Container>
  )
}

searchParams を使用するページ

import { Metadata } from 'next'
import { Suspense } from 'react'

import { Container, PageHeader } from '@/components/layout'

const title = 'Docs'
const description = 'すべての記事の一覧ページです。'

export const metadata: Metadata = {
  title: title,
  description: description,
}

export type DocsPageProps = {
  searchParams: Promise<{ keyword?: string }>
}

export const dynamic = 'force-static'
export const revalidate = 60

export default async function DocsPage(props: DocsPageProps) {
  const searchParams = await props.searchParams
  const keyword = searchParams.keyword

  return (
    <Container className="flex flex-col items-center gap-8 pt-16">
      <PageHeader title={title} description={description} />
      <Suspense fallback={<div>Loading...</div>}>{/* 非同期コンテンツ */}</Suspense>
    </Container>
  )
}

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です