mcpField
W
weaverse-integration

weaverse-integration

github.com/weaverse開発92129 回インストール2 週間前に更新
リポジトリ

weaverse-integration について

既存の Hydrogen プロジェクトに Weaverse を導入する開発者向けのスキルです。既存の規約を保ちながら、プロジェクト分析、SDK 設定、コンポーネント変換、ルート移行、検証を段階的に進めます。

主な機能

  1. 01Hydrogen のバージョンと構成の分析
  2. 02Weaverse SDK と環境変数の設定
  3. 03コンポーネントを編集可能なセクションに変換
  4. 04セクション登録とルート移行
  5. 05ページの段階的な移行

活用シーン

  1. 01既存の Hydrogen ストアに Weaverse を導入
  2. 02販促バナーなどを編集可能なセクションに変換
  3. 03ホームページや商品ページで段階的に Weaverse を有効化

インストール

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

$npx skills add https://github.com/weaverse/shopify-hydrogen-skills --skill weaverse-integration

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

詳細

Weaverse の統合 — 既存の Hydrogen プロジェクト

目的: 現在 Weaverse を使用していない Hydrogen プロジェクトに Weaverse を統合します。このスキルでは、分析 → SDK のセットアップ → コンポーネントの変換 → ルートの移行 → 検証という全工程を案内します。

重要な原則: 既存のプロジェクトを尊重してください。コーディングスタイル、パターン、規約に合わせます。すでに機能しているものは再構成せず、Weaverse で拡張してください。

ライブドキュメント

このスキルのフォルダーから、次のコマンドを実行してください。ヘルパーは兄弟フォルダーにある shopify-hydrogen スキルに含まれているため、パック全体がインストールされていれば ../shopify-hydrogen/scripts/ が存在します。

このスキルを単独でインストールした場合、そのフォルダーは存在せず、次のコマンドは MODULE_NOT_FOUND で失敗します。ヘルパーを一度追加してください:

npx skills add Weaverse/shopify-hydrogen-skills --skill shopify-hydrogen

このスキルには references/ ディレクトリがないため、以下のフェーズがオフラインで参照できる唯一のガイダンスです。ライブドキュメントのコマンドは任意の補足です。

# Always fetch latest docs before making decisions
node ../shopify-hydrogen/scripts/search_weaverse_docs.mjs "existing hydrogen integration"
node ../shopify-hydrogen/scripts/get_weaverse_page.mjs "migration-advanced/existing-hydrogen-integration"
node ../shopify-hydrogen/scripts/search_shopify_docs.mjs "createHydrogenContext"

フェーズ 1:既存のプロジェクトを分析する

コードに手を加える前に、プロジェクトの現在の状態を読み取り、記録してください。

1.1 フレームワークのバージョンを検出する
# Check package.json
cat package.json | grep -E '"react-router"|"@remix-run"|"@shopify/hydrogen"|"@weaverse"'
確認できる内容インストールする Weaverse のバージョン
react-router + @shopify/[email protected]+@weaverse/hydrogen@latest(v5、React Router v7)
@remix-run/react@weaverse/hydrogen@4(v4、Remix)

プロジェクトが Remix(2025.5.0 より前)を使用している場合:

  • まず React Router v7 に移行してから Weaverse v5 を統合するか、ユーザーに確認します
  • または、現在の Remix セットアップに Weaverse v4 を統合します
  • v7 への移行を推奨してください。こちらが今後の方向性です
1.2 コードベースを一覧化する

次のファイルを読み、パターンを記録します:

ファイル確認する内容
package.json依存関係、スクリプト、パッケージマネージャー(npm/yarn/pnpm/bun)
app/root.tsxレイアウト構造、プロバイダー、グローバルスタイル
app/entry.server.tsxCSP のセットアップ、レンダリング方法
server.ts(または server/index.ts)コンテキストの作成、ミドルウェア
app/routes/**ルート構造、ローダーパターン、命名規則
app/components/**コンポーネントのパターン、props、スタイリング方法
app/sections/**セクションが存在する場合は、その構成
app/styles/** または tailwind.config.*スタイリング方法(Tailwind、CSS Modules、styled-components など)
vite.config.tsビルドプラグイン、エイリアス
.env または .env.example既存の環境変数(シークレットは読まないでください)
tsconfig.jsonパスエイリアス、厳密性の設定
1.3 コーディング規約を記録する

次のパターンを記録し、維持してください:

  • コンポーネントのスタイル: 関数宣言、アロー関数、forwardRef のどれを使用しているか
  • エクスポートのスタイル: export default、名前付きエクスポート、export let のどれを使用しているか
  • スタイリング: Tailwind クラス、CSS Modules、styled-components、インラインスタイル
  • 状態管理: フック、コンテキスト、ストア
  • データ取得: ローダーパターン、GraphQL クエリの構造、エラー処理
  • ファイル名: kebab-case、PascalCase、camelCase
  • インポートのスタイル: 絶対パス(~/)と相対パス、名前空間インポートとデフォルトインポート
  • TypeScript: 厳密性、interface と type、ジェネリクスの使用方法
  • コメント: ドキュメントの詳しさ、JSDoc の使用状況

⚠️ 重要: 変換後の Weaverse コンポーネントは、必ずこれらの規約に合わせてください。プロジェクトが function 宣言を使用している場合は、const X = () => を使わないでください。Tailwind を使用している場合は、CSS Modules を導入しないでください。

1.4 変換可能なコンポーネントを特定する

Weaverse のセクションとして適したコンポーネントを探します:

適した候補:

  • ヒーローバナー/スライダー
  • 注目コレクション/商品グリッド
  • お客様の声/レビュー
  • ニュースレター登録
  • プロモーションバナー
  • カスタムコンテンツセクション(画像+テキスト、動画など)
  • フッターセクション(ニュースレター、ソーシャルリンク)
  • コンテンツを編集できるナビゲーションコンポーネント

対象外(変換しない):

  • レイアウトの基本要素(Button、Input、Modal。共有コンポーネントとして維持します)
  • ルートレベルのラッパー
  • カート/チェックアウトのロジックを担うコンポーネント
  • 分析/トラッキングのコンポーネント
  • サーバーユーティリティ

フェーズ 2:Weaverse SDK のインストールと設定

2.1 パッケージのインストール
# Use whatever package manager the project already uses
# React Router v7 (Hydrogen 2025.5.0+)
npm install @weaverse/hydrogen@latest

# Remix (legacy)
npm install @weaverse/hydrogen@4
2.2 環境変数

.env に追加します。

WEAVERSE_PROJECT_ID="provided-by-user"
WEAVERSE_API_KEY="provided-by-user"

.env.example にも追加し(実際の値は入れず)、TypeScript の環境変数の型を更新します。

// Add to the Env type in env.d.ts or wherever the project defines it
WEAVERSE_PROJECT_ID: string;
WEAVERSE_API_KEY: string;
WEAVERSE_HOST?: string;
2.3 app/weaverse/ ディレクトリの作成

以下の 5 つのファイルを作成します。プロジェクトで既に使われているコードスタイル(エクスポート、命名規則、引用符、セミコロン)に合わせてください。

app/weaverse/schema.server.ts — テーマスキーマ
import type { HydrogenThemeSchema } from "@weaverse/hydrogen";
import pkg from "../../package.json";

export let themeSchema: HydrogenThemeSchema = {
  info: {
    version: pkg.version,
    author: "Your Store Name",
    name: "Your Theme Name",
  },
  settings: [
    // Start minimal — add more as you convert components
    {
      group: "Colors",
      inputs: [
        {
          type: "color",
          name: "colorPrimary",
          label: "Primary Color",
          defaultValue: "#000000",
        },
        {
          type: "color",
          name: "colorBackground",
          label: "Background Color",
          defaultValue: "#ffffff",
        },
        {
          type: "color",
          name: "colorText",
          label: "Text Color",
          defaultValue: "#1a1a1a",
        },
      ],
    },
    {
      group: "Typography",
      inputs: [
        {
          type: "range",
          name: "headingBaseSize",
          label: "Heading Base Size",
          configs: { min: 14, max: 32, step: 1, unit: "px" },
          defaultValue: 28,
        },
        {
          type: "range",
          name: "bodyBaseSize",
          label: "Body Base Size",
          configs: { min: 12, max: 20, step: 1, unit: "px" },
          defaultValue: 16,
        },
      ],
    },
  ],
};
app/weaverse/style.tsx — グローバルスタイル

プロジェクトの既存のグローバルスタイル(CSS ファイル、Tailwind の設定、ルートレイアウト)を確認し、既存の設定に統合できる CSS 変数を作成します。

import { useThemeSettings } from "@weaverse/hydrogen";

export function GlobalStyle() {
  let settings = useThemeSettings();
  if (!settings) return null;

  return (
    <style
      id="weaverse-global-style"
      key="weaverse-global-style"
      suppressHydrationWarning
      dangerouslySetInnerHTML={{
        __html: `
          :root {
            --color-primary: ${settings.colorPrimary};
            --color-bg: ${settings.colorBackground};
            --color-text: ${settings.colorText};
            --heading-base: ${settings.headingBaseSize}px;
            --body-base: ${settings.bodyBaseSize}px;
          }
        `,
      }}
    />
  );
}
app/weaverse/components.ts — コンポーネントレジストリ
import type { HydrogenComponent } from "@weaverse/hydrogen";

// Import converted sections here — start empty, add as you convert
// MUST use namespace imports: import * as X, NOT import X from
export let components: HydrogenComponent[] = [
  // Sections will be added during Phase 3
];
app/weaverse/index.tsx — WeaverseContent
import { WeaverseHydrogenRoot } from "@weaverse/hydrogen";
import { components } from "./components";

export function WeaverseContent() {
  return (
    <WeaverseHydrogenRoot
      components={components}
      errorComponent={GenericError}
    />
  );
}

プロジェクトに既存のエラーコンポーネントがあれば使用し、なければ最小限の GenericError を作成します。

app/weaverse/csp.ts — コンテンツセキュリティポリシー
export function getWeaverseCsp(request: Request, context: any) {
  let url = new URL(request.url);
  let weaverseHost = context.env?.WEAVERSE_HOST || "https://weaverse.io";
  let isDesignMode = url.searchParams.get("weaverse_design_mode") === "true";

  let weaverseHosts = [
    new URL(weaverseHost).host,
    "weaverse.io",
    "*.weaverse.io",
    "shopify.com",
    "*.shopify.com",
    "*.myshopify.com",
  ];

  let updatedCsp: Record<string, string[] | string | boolean> = {
    frameAncestors: weaverseHosts,
    defaultSrc: ["'self'", "data:", ...weaverseHosts],
    scriptSrc: ["'self'", "'unsafe-inline'", ...weaverseHosts],
    styleSrc: ["'self'", "'unsafe-inline'", ...weaverseHosts],
    connectSrc: ["'self'", ...weaverseHosts],
  };

  if (isDesignMode) {
    updatedCsp.frameAncestors = ["*"];
  }

  return updatedCsp;
}
2.4 サーバーコンテキストの更新

既存のコンテキストファイル(通常は server.ts または app/lib/context.ts)を変更します。

// ADD these imports
import { WeaverseClient } from "@weaverse/hydrogen";
import { themeSchema } from "~/weaverse/schema.server"; // adjust path alias
import { components } from "~/weaverse/components";

// INSIDE createAppLoadContext, after hydrogenContext is created:
return {
  ...hydrogenContext,
  weaverse: new WeaverseClient({
    ...hydrogenContext,
    request,
    cache,
    themeSchema,
    components,
  }),
};

コンテキストの作成方法を再構成しないでください。 既存の戻り値オブジェクトに Weaverse クライアントを展開して追加するだけです。

2.5 ルートファイルとエントリーファイルの更新
app/root.tsx — withWeaverse でラップする
import { withWeaverse } from "@weaverse/hydrogen";
import { GlobalStyle } from "~/weaverse/style";

// Keep their existing Layout/App components untouched
// Only change: wrap the default export

// BEFORE:
// export default function App() { ... }

// AFTER:
function App() {
  // ... their existing App code, unchanged
}
export default withWeaverse(App);

Layout コンポーネントの <head> 内に <GlobalStyle /> を追加します。

app/entry.server.tsx — Weaverse の CSP を追加する
import { getWeaverseCsp } from "~/weaverse/csp";

// Inside handleRequest, merge Weaverse CSP with existing:
const { nonce, header, NonceProvider } = createContentSecurityPolicy({
  ...getWeaverseCsp(request, context),
  shop: {
    checkoutDomain: context.env?.PUBLIC_CHECKOUT_DOMAIN || context.env?.PUBLIC_STORE_DOMAIN,
    storeDomain: context.env?.PUBLIC_STORE_DOMAIN,
  },
});

既存の CSP 設定とマージしてください。置き換えないでください。


フェーズ 3:既存のコンポーネントを Weaverse セクションに変換する

これは最も重要なフェーズです。ユーザーの既存コンポーネントを、正確な見た目と動作を維持したまま Weaverse で編集可能なセクションに変換します。

3.1 変換方針

変換可能なコンポーネントごとに、以下を行います。

  1. 元のコンポーネントを読む — props、state、データ取得、スタイルを把握します
  2. Weaverse ラッパーを作成する — schema と必要に応じて loader を追加します
  3. 元のレンダリングを維持する — JSX を書き換えず、ラップするだけにします
  4. components.ts に登録する — 名前空間インポートを追加します
3.2 変換パターン

変換前のコンポーネント:

// app/components/hero-banner.tsx
interface HeroBannerProps {
  heading: string;
  subtitle: string;
  backgroundImage: string;
  alignment: "left" | "center";
}

function HeroBanner({ heading, subtitle, backgroundImage, alignment }: HeroBannerProps) {
  return (
    <section className="relative bg-cover bg-center" style={{ backgroundImage: `url(${backgroundImage})` }}>
      <div className={`flex flex-col ${alignment === 'center' ? 'items-center text-center' : 'items-start'}`}>
        <h1 className="text-4xl font-bold">{heading}</h1>
        <p className="text-xl mt-4">{subtitle}</p>
      </div>
    </section>
  );
}
export default HeroBanner;

変換後のコンポーネント:

// app/sections/hero-banner.tsx (or keep original path, just add schema)
import type { HydrogenComponentProps } from "@weaverse/hydrogen";
import { createSchema } from "@weaverse/hydrogen";

interface HeroBannerProps extends HydrogenComponentProps {
  heading: string;
  subtitle: string;
  backgroundImage: string;
  alignment: "left" | "center";
}

function HeroBanner({ heading, subtitle, backgroundImage, alignment, children, ...rest }: HeroBannerProps) {
  return (
    <section {...rest} className="relative bg-cover bg-center" style={{ backgroundImage: `url(${backgroundImage})` }}>
      <div className={`flex flex-col ${alignment === 'center' ? 'items-center text-center' : 'items-start'}`}>
        <h1 className="text-4xl font-bold">{heading}</h1>
        <p className="text-xl mt-4">{subtitle}</p>
      </div>
      {children}
    </section>
  );
}
export default HeroBanner;

export let schema = createSchema({
  type: "hero-banner",
  title: "Hero Banner",
  settings: [
    {
      group: "Content",
      inputs: [
        { type: "text", name: "heading", label: "Heading", defaultValue: "Welcome" },
        { type: "textarea", name: "subtitle", label: "Subtitle" },
        { type: "image", name: "backgroundImage", label: "Background Image" },
        {
          type: "toggle-group",
          name: "alignment",
          label: "Alignment",
          configs: {
            options: [
              { value: "left", label: "Left" },
              { value: "center", label: "Center" },
            ],
          },
          defaultValue: "center",
        },
      ],
    },
  ],
  presets: {
    heading: "Welcome",
    alignment: "center",
  },
});

主な変更点:

  • HydrogenComponentProps を拡張する(children、loaderData、Weaverse の内部情報を追加)
  • ルート要素で {...rest} を展開する(Studio との連携に必須)
  • ネストしたセクションを受け入れられるコンポーネントでは {children} をレンダリングする
  • createSchema() を使って schema をエクスポートする
  • JSX の構造とスタイルを完全に同じに保つ
3.3 スキーマ設計ルール

変換したコンポーネントのスキーマを作成する場合:

元の prop の型スキーマの入力型
string(短いテキスト)text
string(長いテキスト)textarea または richtext
string(URL)url
string(画像パス)image
string(16 進カラーコード)color
numberrange(適切な min/max/step を設定)
booleanswitch
string(列挙型)select または toggle-group
Shopify データを含むオブジェクトproduct、collection、blog など

設定を論理的にグループ化します。 コンポーネントに適した形にし、通常は次のようにします。

  • 「コンテンツ」グループ — テキスト、画像、リンク
  • 「デザイン」グループ — 色、余白、レイアウトオプション
  • 「高度な設定」グループ — 表示設定、カスタム CSS クラス
3.4 データ取得を行うコンポーネントの変換

元のコンポーネントがデータを取得する場合(例:特集コレクション)、データ取得処理を Weaverse loader に変換します。

import type { ComponentLoaderArgs } from "@weaverse/hydrogen";

type SectionData = {
  collectionHandle: string;
  count: number;
};

export let loader = async ({ weaverse, data }: ComponentLoaderArgs<SectionData>) => {
  if (!data?.collectionHandle) return null;
  return weaverse.storefront.query(COLLECTION_QUERY, {
    variables: { handle: data.collectionHandle, first: data.count ?? 8 },
  });
};

プロジェクトで既に使用されている GraphQL クエリとフラグメントを使用し、書き換えないでください。共有クエリを含む graphql/ ディレクトリがある場合は、そこからインポートします。

3.5 変換したコンポーネントの登録

app/weaverse/components.ts を更新します。

import * as HeroBanner from "~/sections/hero-banner";
import * as FeaturedCollection from "~/sections/featured-collection";
// ... other converted components

export let components: HydrogenComponent[] = [
  HeroBanner,
  FeaturedCollection,
  // ...
];

必ず import * as X を使用してください。 import X from は使用しないでください。これは最もよくある間違いです。


フェーズ 4:ルートの更新

Weaverse で編集可能にする各ルートに対して、以下を行います。

4.1 ルートの変換パターン
// BEFORE — original route
import { useLoaderData } from "react-router"; // or "@remix-run/react"
import HeroBanner from "~/components/hero-banner";
import ProductGrid from "~/components/product-grid";

export async function loader({ context, params }: LoaderFunctionArgs) {
  const productData = await context.storefront.query(PRODUCT_QUERY, { ... });
  return { product: productData.product };
}

export default function Homepage() {
  const { product } = useLoaderData<typeof loader>();
  return (
    <div>
      <HeroBanner heading="Sale" subtitle="Big deals" />
      <ProductGrid products={product} />
    </div>
  );
}
// AFTER — Weaverse-enabled route
import { WeaverseContent } from "~/weaverse";

export async function loader({ context, params }: LoaderFunctionArgs) {
  // Keep existing data loading
  const productData = await context.storefront.query(PRODUCT_QUERY, { ... });

  // ADD Weaverse page loading
  const weaverseData = await context.weaverse.loadPage({ type: "INDEX" });

  return {
    product: productData.product,
    weaverseData,
  };
}

export default function Homepage() {
  // Render Weaverse content — it will use the registered components
  return <WeaverseContent />;
}
4.2 ページタイプ
ルートtype の値
ホームページ(_index)"INDEX"
商品ページ"PRODUCT"(handle: params.productHandle を指定)
コレクションページ"COLLECTION"(handle: params.collectionHandle を指定)
コレクション一覧"ALL_PRODUCTS"
ブログ"BLOG"
記事"ARTICLE"(handle: params.articleHandle を指定)
カスタムページ"PAGE"(handle: params.pageHandle を指定)
カスタムテンプレート"CUSTOM"
4.3 段階的な移行(推奨)

すべてのルートを一度に変換する必要はありません。次の順に始めてください。

  1. ホームページ — 影響が最も大きく、通常は最も簡単です
  2. 商品ページ — マーチャントにとっての価値が高いです
  3. コレクションページ — ビジュアルマーチャンダイジングが可能になります
  4. その他のページ — 必要に応じて対応します

まだ変換していないルートは、そのままにしておいてください。Weaverse は Weaverse 以外のルートに干渉しません。


フェーズ 5:エッジケースへの対応

5.1 既存のレイアウトコンポーネント

プロジェクトに共通のレイアウトコンポーネント(ヘッダー、フッター、ナビゲーション)がある場合:

  • ヘッダー/フッター — ひとまず Weaverse の外に置き、root.tsx の Layout でレンダリングします
  • または、ユーザーが編集可能にしたい場合は、Weaverse コンポーネントに変換します
  • どちらの方法を希望するか、ユーザーに確認してください
5.2 共通コンポーネント(ボタン、入力欄など)

プリミティブ/共通コンポーネントは変換しないでください。これらは app/components/ に置いたまま、Weaverse セクション内で使用します。

5.3 サードパーティ連携

プロジェクトで以下を使用している場合:

  • アナリティクス(GA4、Segment など)— ルートローダーまたはルートレイアウトに保持します
  • A/B テスト — Weaverse のページレンダリングの外に保持します
  • カスタムミドルウェア — Weaverse CSP がサードパーティのスクリプトをブロックしないようにします
  • CMS データ(Contentful、Sanity など)— 併用できます。Weaverse はビジュアルレイアウトを処理し、外部 CMS は構造化コンテンツを処理します
5.4 TypeScript 型

プロジェクトの型定義に追加します。

// Wherever the project defines AppLoadContext
interface AppLoadContext {
  // ... existing properties
  weaverse: import("@weaverse/hydrogen").WeaverseClient;
}

フェーズ 6:確認チェックリスト

統合後、次の項目を確認します。

  • npm run dev がエラーなしで起動する
  • 既存のルートが引き続き正しくレンダリングされる(ビジュアルリグレッションチェック)
  • ローカル開発 URL で Weaverse Studio のプレビューが読み込まれる
  • 変換したコンポーネントが Weaverse Studio のコンポーネントピッカーに表示される
  • Studio > Theme > Customize にテーマ設定が表示される
  • 変換したコンポーネントが元のコンポーネントと同一にレンダリングされる
  • コンポーネントスキーマで適切な編集可能設定が公開される
  • データを取得するセクションでデータが正しく読み込まれる
  • npm run build がエラーなしで完了する
  • TypeScript が新たなエラーなしでコンパイルされる
  • カート、チェックアウト、顧客アカウントの各フローが引き続き機能する
  • CSP に関連するコンソールエラーがない

避けるべきよくある間違い

間違い修正方法
import * as X ではなく import X from を使うコンポーネント登録では必ず名前空間インポートを使います
ルート要素に {...rest} を付け忘れるWeaverse Studio のドラッグ&ドロップ操作に必須です
コンテナコンポーネントで {children} をレンダリングしないネストされたセクションに必須です
既存の CSP をマージせずに上書きするWeaverse CSP を既存の設定に展開してマージします
コンポーネントの JSX を「改善するため」に書き換える元のレンダリングを正確に保持します
すべてのコンポーネントを一度に変換するまずセクションを変換し、プリミティブは共通コンポーネントのままにします
スキーマで inspector を使うsettings を使います。inspector は非推奨です
app/ の外に app/weaverse/ を作成するapp ディレクトリ内に置く必要があります
型定義に環境変数を追加し忘れるEnv 型に WEAVERSE_* を追加します

クイックリファレンス — ファイル変更の概要

ファイル操作
package.json@weaverse/hydrogen 依存関係を追加
.envWEAVERSE_PROJECT_ID、WEAVERSE_API_KEY を追加
app/weaverse/schema.server.ts作成 — テーマスキーマ
app/weaverse/style.tsx作成 — グローバルスタイルコンポーネント
app/weaverse/components.ts作成 — コンポーネントレジストリ
app/weaverse/index.tsx作成 — WeaverseContent ラッパー
app/weaverse/csp.ts作成 — CSP 設定
server.ts(またはコンテキストファイル)変更 — コンテキストに WeaverseClient を追加
app/root.tsx変更 — withWeaverse でラップし、<GlobalStyle /> を追加
app/entry.server.tsx変更 — Weaverse CSP を統合
app/sections/*.tsx作成/変更 — 変換済みコンポーネント
ルートファイル変更 — weaverse.loadPage() を追加し、<WeaverseContent /> をレンダリング
型定義変更 — WEAVERSE_* 環境変数と weaverse コンテキストを追加
.gitignore確認 — .react-router/ が無視されていること(RRv7 プロジェクト)

コメント