mcpField
T
tanstack-start

tanstack-start

github.com/vercel-labs開発18.9k201 回インストール1 日前に更新
リポジトリ

tanstack-start について

json-render の仕様から TanStack Start のページとルートを生成・描画する React 統合です。ページデータ、メタデータ、静的パス向けのサーバーヘルパーと、ルートに応じたフォールバック UI を備えています。

主な機能

  1. 01TanStack Start で json-render ページを描画
  2. 02ルートパターンとレイアウトの定義
  3. 03ページデータとメタデータの取得
  4. 04静的パスの生成
  5. 05ルートに応じた読み込み・エラー UI

活用シーン

  1. 01アプリ仕様からページを構築
  2. 02パラメーター付きルートのデータ取得
  3. 03動的ページの静的パス生成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/vercel-labs/json-render --skill tanstack-start

インストール後、Claude Code で/tanstack-startを入力して読み込まれたか確認します。

詳細

@json-render/tanstack-start

TanStack Start アプリで、json-render 仕様に記述された完全なページまたはルートが必要な場合に、この統合を使用します。

インストール

npm install @json-render/core @json-render/react @json-render/tanstack-start

アプリケーション仕様

生成カタログに、サーバーセーフな組み込み定義を含めます。レンダラーがこれらのコンポーネント実装を提供します。

import { defineCatalog } from "@json-render/core";
import {
  schema,
  startComponentDefinitions,
} from "@json-render/tanstack-start/server";

const catalog = defineCatalog(schema, {
  components: {
    ...startComponentDefinitions,
    Card: cardDefinition,
    Shell: shellDefinition,
    Navigation: navigationDefinition,
    Home: homeDefinition,
    Post: postDefinition,
  },
  actions: {},
});

次に、StartAppSpec と TanStack Router のルートパターンを使用します。

import type { StartAppSpec } from "@json-render/tanstack-start";

export const spec: StartAppSpec = {
  metadata: {
    title: { default: "Site", template: "%s | Site" },
  },
  layouts: {
    main: {
      root: "shell",
      elements: {
        shell: { type: "Shell", props: {}, children: ["nav", "slot"] },
        nav: { type: "Navigation", props: {}, children: [] },
        slot: { type: "Slot", props: {}, children: [] },
      },
    },
  },
  routes: {
    "/": {
      layout: "main",
      metadata: { title: "Home" },
      page: {
        root: "home",
        elements: {
          home: { type: "Home", props: {}, children: [] },
        },
      },
    },
    "/posts/$slug": {
      layout: "main",
      loader: "post",
      staticParams: [{ slug: "hello" }],
      page: {
        root: "post",
        elements: {
          post: {
            type: "Post",
            props: { value: { $state: "/post" } },
            children: [],
          },
        },
      },
    },
  },
};

名前付きパラメーターには /posts/$slug、スプラットには /docs/$ を使用します。スプラットのローダーパラメーターは、_splat の下にスラッシュ区切りの文字列として格納されます。RFC 6902 パッチを生成する際は、ルートキーのスラッシュを ~1 としてエスケープしてください。

すべてのレイアウトに Slot 要素が必要です。startComponentDefinitions を通じて Slot と Link を宣言し、利用側が React 実装を登録する必要がないようにしてください。

サーバーヘルパー

import { createStartApp } from "@json-render/tanstack-start/server";

export const { getPageData, getHead, getStaticPaths } = createStartApp({
  spec,
  loaders: {
    post: async ({ slug }) => ({ post: await getPost(slug as string) }),
  },
});

状態のマージ順は、アプリケーションの状態、レイアウトの状態、ページの状態、ローダーデータの順です。getHead は、アプリとルートのメタデータを TanStack の meta および links ディスクリプターにマージします。getStaticPaths は、静的ルートと staticParams を持つ動的ルートを含めます。TanStack Start のトップレベルの pages プラグインオプションには、これらの文字列を { path } オブジェクトに変換して渡してください。ローダーパラメーターは URL デコードされますが、生成されるパスでは staticParams の値が URL エンコードされます。ルートマッチングでは末尾のスラッシュを任意として扱い、エンコード済みまたはデコード済みのパス名表現を受け入れるため、ローダーデータとメタデータは同じ静的ルートを解決します。

ルートの接続

import { createFileRoute, notFound } from "@tanstack/react-router";
import {
  PageRenderer,
  StartErrorBoundary,
  StartLoading,
  StartNotFound,
} from "@json-render/tanstack-start";
import { getHead, getPageData } from "@/lib/json-app";

export const Route = createFileRoute("/$")({
  loader: async ({ location }) => {
    const data = await getPageData({ pathname: location.pathname });
    if (!data) throw notFound();
    return data;
  },
  head: ({ match }) => getHead({ pathname: match.pathname }),
  component: () => <PageRenderer {...Route.useLoaderData()} />,
  pendingComponent: StartLoading,
  errorComponent: StartErrorBoundary,
  notFoundComponent: StartNotFound,
});

TanStack Router のローダーはサーバーとクライアントの両方で実行されます。仕様ファクトリーまたは名前付きローダーが認証情報、データベースクライアント、あるいはサーバー専用のインポートを使用する場合は、getPageData と getHead を TanStack Start の createServerFn でラップしてください。そのサーバーコードを同形ルートローダーに直接インポートしないでください。

ルートプロバイダー

ルートルートの Outlet を StartAppProvider でラップします。HeadContent をレンダリングして、getHead のメタデータをドキュメントに反映させてください。

import {
  createRootRoute,
  HeadContent,
  Outlet,
  Scripts,
} from "@tanstack/react-router";
import { StartAppProvider } from "@json-render/tanstack-start";
import { spec } from "@/lib/spec";

export const Route = createRootRoute({
  component: () => (
    <html lang="en">
      <head>
        <HeadContent />
      </head>
      <body>
        <StartAppProvider
          registry={registry}
          handlers={handlers}
          spec={spec}
        >
          <Outlet />
        </StartAppProvider>
        <Scripts />
      </body>
    </html>
  ),
});

TanStack Router の pendingComponent、errorComponent、notFoundComponent オプションには、それぞれ StartLoading、StartErrorBoundary、StartNotFound を使用します。StartAppProvider に spec を渡すと、各コンポーネントはマッチしたルートに対応するフォールバックを選択します。明示的なフォールバックプロパティは、その参照より優先されます。名前付き $computed 実装は、StartAppProvider.functions を通じて渡してください。デフォルトのエラーバウンダリーはルーターを無効化し、ユーザーが 再試行 を選択すると、失敗したローダーを再実行します。

React コンポーネントは @json-render/tanstack-start からインポートしてください。schema、createStartApp、matchRoute、resolveMetadata、および静的パスヘルパーは @json-render/tanstack-start/server からインポートしてください。

コメント