記事を読み込んでいます…

ポートフォリオに制作の記録やお知らせを載せたい。でも、記事を更新するたびにコードを編集するのは少し手間です。
そこで、原稿を書く場所とサイトのデザインを分けて管理できるヘッドレスCMS「genko.me」を制作しました。自分のポートフォリオでも、ブログと制作実績の管理をmicroCMSから「genko.me」へ移しています。
この記事では、新しくブログを追加する場合を例に、記事の作成からサイトでの表示、公開前のプレビューまでを紹介します。既存データの移行手順ではなく、まず1件の記事を表示するための導入ガイドです。
genko.meは、タイトルや本文、画像などの原稿を管理し、APIを通してサイトやアプリへ届けるCMSです。サイトそのものを自動で作るサービスではなく、見た目は自分のサイト側で設計できます。
管理画面では余白や文字の読みやすさ、編集時の操作の流れにこだわりました。スキーマで必要な入力項目を決めて、原稿を書き、公開する。日々の更新に集中できる場所を目指しています。
genko.me自体はNext.js専用ではありません。JavaScript/TypeScript向けの取得用SDKとREST APIも用意しています。今回は、取得から表示までを任せられる部品があるNext.js App Routerで説明します。
/blog:公開記事の一覧
/blog/記事ID:記事の詳細
同じ詳細ページでの保存済み下書きのプレビュー
コード例はNext.js 16以降・React 19のApp RouterとNode.jsランタイムを対象にしています。CLIにはNode.js 20.12以降が必要です。利用するNext.jsのNode.js要件も満たす環境を用意してください。
以下ではAPIのエンドポイントを「blog」、タイトルのフィールドIDを「title」、本文を「body」とします。自分のAPIが「blogs」など別の名前なら、コードのclient.blogもその名前に合わせてください。
genko.meに登録・ログインしてワークスペースを開き、APIを追加します。API名は「ブログ」、エンドポイントは「blog」、形式は「リスト形式」にします。
スキーマには、テキスト型の「title」とリッチテキスト型の「body」を追加します。どちらも必須にしておくと、タイトルや本文が空のまま公開するのを防げます。
作成したAPIから「新しい原稿」を開き、記事を1件入力します。エディターの「設定」で公開状態を「公開」に変更し、「保存する」を押してください。下書きのままでは、通常の記事一覧には表示されません。
ワークスペースのAPIキー管理画面で、サイト用のキーを発行します。管理画面のURLが https://genko.me/your-workspace なら、ワークスペースIDは your-workspace です。
Next.jsプロジェクトのpackage.jsonがあるディレクトリで、使用するパッケージマネージャーに合わせて、次のどちらかを実行します。
npx @genko-me/cli initpnpmの場合:
pnpm dlx @genko-me/cli initCLIでワークスペースIDとAPIキーを入力し、同期するAPIとして「blog」を選びます。必要なパッケージの追加と、スキーマ・接続設定の生成が行われます。
lib/schema.ts:管理画面のスキーマから生成された型とAPI定義
lib/client.ts:サイトから利用するクライアント
genko.config.json:次回の同期に使う設定
src/app構成では、接続ファイルはsrc/libに生成されます。以降のページもsrc/app配下に配置してください。コード例の「@/」はlibへアクセスできるimportエイリアスを想定しています。
新しく入力したキーは.env.localに保存されます。APIキーをGitやブラウザ向けのコードへ含めないでください。CLIはページ自体を生成しないので、次のコードをサイト側に追加します。
app/blog/page.tsxに、公開記事の一覧を配置します。
import { client } from "@/lib/client";
import { List, ListItem, Pagination, Error, Null } from "@genko-me/react/next";
export default function BlogPage() {
return (
<main>
<h1>ブログ</h1>
<List api={client.blog} limit={6} orders="-publishedAt" href="/blog/{id}">
<article>
<h2><ListItem id="title" /></h2>
</article>
<Pagination />
<Error template />
<Null>公開されている記事はありません。</Null>
</List>
</main>
);
}Listの中に書いたarticleが、記事1件ごとに繰り返されます。表示する項目はListItemで指定します。Paginationは一覧全体のページ送りとして扱われ、記事ごとには繰り返されません。
開発サーバーを起動して/blogを開き、管理画面で公開した記事のタイトルが表示されれば接続できています。環境変数を追加する前からサーバーを起動していた場合は、再起動してください。
app/blog/[id]/page.tsxに、記事IDを受け取るページを追加します。
import { client } from "@/lib/client";
import { View, ViewItem, Error, Null } from "@genko-me/react/next";
type Props = {
params: Promise<{ id: string }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
};
export default async function BlogDetail({ params, searchParams }: Props) {
const { id } = await params;
return (
<main>
<View api={client.blog} id={id} searchParams={searchParams}>
<h1><ViewItem id="title" /></h1>
<ViewItem id="body" className="article-body" />
<Error template />
<Null>記事が見つかりません。</Null>
</View>
</main>
);
}ViewにAPIと記事IDを渡し、ViewItemで表示するフィールドを選びます。見出しはh1で囲むなど、自分のHTMLでレイアウトを組めます。
List・View・本文・ページ送りには標準の装飾を付けていません。classNameやstyleとサイト側のCSSで整えます。たとえば本文なら、既存のグローバルCSSへ次のように追加できます。
.article-body { line-height: 1.9; }
.article-body p { margin-block: 1em; }
.article-body h2 { margin-block: 2em 0.75em; font-size: 1.5em; }
.article-body img { max-width: 100%; height: auto; }
.article-body pre { overflow-x: auto; }管理画面のAPI設定で、プレビューURLを自分のサイトに合わせて設定します。
https://your-site.example/blog/{id}?draftKey={key}ローカルで確認する場合は、ドメイン部分を実際に起動しているlocalhostのURLとポートに置き換えます。
原稿を下書きとして保存してから「プレビュー」を押すと、普段の詳細ページに保存済みの下書きが表示されます。未保存の入力をそのまま反映する機能ではありません。
ここで必要なのが、詳細ページのsearchParamsをViewへ渡す記述です。これを省くと、SDKはURLのdraftKeyを受け取れません。専用のRoute HandlerやProxyを追加する必要はありません。
下書きプレビュー中の通知と終了ボタンには標準デザインがあります。プレビューURLには下書きへアクセスするためのキーが含まれるので、公開リンクとして共有しないでください。
ホスティング先にもGENKO_API_KEYを設定する。.env.localは自動では引き継がれません。
公開記事の一覧・詳細が表示され、管理画面から下書きプレビューを開けることを確認する。
プレビューの終了後に通常表示へ戻ること、記事数が増えたらページ送りが動くことを確認する。
表示部品はNode.jsランタイムで動かす。静的エクスポートやEdgeランタイムは対象外です。
通常表示も既定では毎回最新データを取得します。キャッシュしたい場合だけListやViewにcache={60}のように秒数を指定します。下書きプレビューはキャッシュしません。
スキーマを変更したら、npx @genko-me/cli pull、またはpnpm dlx @genko-me/cli pullで型を同期します。初期化済みのプロジェクトでinitを繰り返す必要はありません。
一覧が空なら、まず記事が「公開」で保存されているか確認してください。接続先が見つからない場合は、ワークスペースIDとエンドポイントの綴りを確認します。「blog」と「blogs」は別のAPIです。
APIキーが読み込めているか、キーを発行したワークスペースと接続先が一致しているかも確認します。取得エラーを見落とさないよう、導入中はコード例のErrorを置いておくと切り分けしやすくなります。
genko.meは無料で始められます。まずはブログやお知らせなど、小さな更新欄から試してみてください。この記事ではNext.jsの例を紹介しましたが、取得処理を自分で書く場合のSDKやREST APIについてもドキュメントにまとめています。
自分のポートフォリオでも使いながら改善を続けています。導入で迷ったところや、原稿を書くときに気になったことがあれば、感想を聞かせてもらえるとうれしいです。
genko.meを開く
クイックスタート
実際に使用しているポートフォリオ
※この記事の手順は2026年9月6日時点のものです。最新の対応範囲と手順はドキュメントを確認してください。