mcpField
B
building-web-artifacts

building-web-artifacts

github.com/osmontero開発1689 回インストール今日更新
リポジトリ

building-web-artifacts について

opencodeでフロントエンドのWebアーティファクトを作るスキルです。Reactプロジェクトの初期化から単一HTMLへのバンドルまでを扱い、デザイン、状態管理、アクセシビリティ、検証も案内します。

主な機能

  1. 01React + TypeScriptプロジェクトの初期化
  2. 02Parcelによる単一HTMLへのバンドル
  3. 03デザインとテーマ設定のガイド
  4. 04コンポーネント状態とアクセシビリティへの対応
  5. 05パフォーマンスと表示検証のガイド

活用シーン

  1. 01会話で共有するWebアーティファクトの作成
  2. 02データ状態を持つフロントエンド画面の構築
  3. 03アーティファクトのアクセシビリティと表示の確認

インストール

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

$npx skills add https://github.com/osmontero/opencode-skills --skill building-web-artifacts

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE.txt
scripts/
bundle-artifact.sh
init-artifact.sh

詳細


Web アーティファクトの構築

高機能なフロントエンドの opencode アーティファクトを構築するには、次の手順に従ってください。

  1. scripts/init-artifact.sh を使用してフロントエンドのリポジトリを初期化します
  2. 生成されたコードを編集してアーティファクトを開発します
  3. scripts/bundle-artifact.sh を使用して、すべてのコードを単一の HTML ファイルにバンドルします
  4. アーティファクトファイルを保存し、その保存場所をユーザーに知らせます
  5. (任意)アーティファクトをテストします

スタック:React 18 + TypeScript + Vite + Parcel(バンドル)+ Tailwind CSS + shadcn/ui

デザインとスタイルのガイドライン

必須のサブスキル: コンポーネントを記述する前に designing-frontend-interfaces を使用してください。最初にデザインブリーフを作成し、トークンブロックを確定します。shadcn のデフォルトは出発点であって、デザインではありません。変更せずにそのまま使うと、このセクションで警告しているありきたりな出力になります。

出荷前に次のスキルも必須です。状態を網羅するための designing-user-experience と、キーボードおよびスクリーンリーダーのサポートを実現するための building-accessible-interfaces です。

避けるべき、特定の「安っぽい」パターン: すべてを中央揃えの max-w-4xl にする、白地に紫/バイオレットから青へのグラデーションを使う、すべての要素に一律で rounded-lg を使う、あらゆる場所に shadow-md を使う、表示用フォントに Inter や system-ui を使う、本文に text-gray-500 を使う、そしてヒーロー → 3 つの機能カード → CTA という骨組みです。

Tailwind を設定し、デフォルトをそのまま受け入れない

Tailwind のデフォルトは、あくまでデフォルトのパレットです。そのまま使うと、アーティファクトの見た目がどれも同じになってしまいます。ブリーフで定めたトークンブロックを使って上書きしてください。

// tailwind.config.js
export default {
  theme: {
    extend: {
      colors: {
        base: "#f7f6f0", surface: "#fffffb", line: "#dcded1",
        ink: { DEFAULT: "#1a271a", 2: "#4a5a46", 3: "#79876f" },
        accent: { DEFAULT: "#2f6b3c", ink: "#f4fbf5" },
      },
      fontFamily: {
        display: ['"Young Serif"', "Georgia", "serif"],
        text: ['"Work Sans"', "system-ui", "sans-serif"],
      },
      borderRadius: { DEFAULT: "2px" },   // ONE radius
    },
  },
};

これで bg-base、text-ink-2、border-line、font-display に意味を持たせられ、1 つのファイルでテーマを切り替えられます。applying-themes スキルには、コントラスト検証済みのすぐに使える 10 種類のパレットが用意されています。

また、別の値を使うと決めた場合は、shadcn のデフォルトの radius 変数も無効にしてください。globals.css の --radius は、すべてのコンポーネントに暗黙的に適用されます。

コンポーネントと状態の要件

アーティファクト内のデータ駆動型コンポーネントには、必要な状態をすべて揃える必要があります。状態の一覧は designing-user-experience を参照してください。自己完結型のアーティファクトでは、これらを簡単に見落としがちです。通常、見落としを防ぐ実際のバックエンドがないためです。

if (error)          return <ErrorState onRetry={refetch} message={...} />;
if (loading)        return <Skeleton />;              // matching the real layout
if (!items.length)  return query ? <NoResults query={query} onClear={...} />
                                 : <FirstRun onCreate={...} />;
return <List items={items} />;

2 種類の空状態はそれぞれ異なるため、どちらも必要です。生成されたアーティファクトで最もよくある手抜きは、どちらにも No data と表示することです。

アーティファクトのアクセシビリティ

shadcn/ui は Radix を基盤としているため、意図どおりに使えば、そのプリミティブはアクセシブルです。問題は、その周囲に追加するものから生じます。

  • アイコンのみのボタンには aria-label が必要です。Radix がラベルを推測することはできません
  • カスタムの <div onClick> ハンドラーは Radix が提供する機能をすべて迂回します。<Button> を使用してください
  • フォーカスリングを取り除く className の上書き(代わりのリングを指定せずに focus:outline-none を使うなど)は、キーボード操作を妨げます
  • チャートやキャンバスにはテキストによる代替が必要です。判明した内容を説明するキャプションを付けてください
  • テーマ設定後にコントラストを確認してください。Radix は色をチェックしません

パフォーマンス

アーティファクトは自己完結型の単一ファイルなので、バンドルサイズがそのまま全体の読み込み時間になります。

  • フォントは base64 の woff2 としてインライン化し、使用する文字に絞り込んでください。 完全な TTF は、バンドルの残りすべてより大きくなる場合があります。
  • アイコンライブラリをインポートしないでください。 import { X } from "lucide-react" は、ツリーシェイキングの動作によっては、ライブラリ全体を取り込む可能性があります。個々の SVG を貼り付けてください。
  • 約 200 行を超えるリストは仮想化してください。 DOM ノードを何千個も描画すると、タブがフリーズします。
  • 大きなリスト内の行には React.memo を使用し、キーを安定させてください。
  • 外部へのリクエストは行わないでください。 アーティファクトは、CDN、リモートフォント、fetch をブロックする CSP のもとで実行されることがよくあります。すべてインライン化する必要があります。

検証

アーティファクトを提示する前に、bundle.html を開いて確認してください。

python3 -c "
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
    b = p.chromium.launch(); pg = b.new_page(viewport={'width':1440,'height':900})
    errs=[]; pg.on('console', lambda m: m.type=='error' and errs.append(m.text))
    pg.on('pageerror', lambda e: errs.append(str(e)))
    pg.goto('file://$PWD/bundle.html'); pg.wait_for_timeout(1200)
    pg.screenshot(path='/tmp/artifact.png', full_page=True)
    pg.set_viewport_size({'width':390,'height':844})
    pg.screenshot(path='/tmp/artifact-mobile.png', full_page=True)
    print('CONSOLE ERRORS:', errs); b.close()"

その後、両方のスクリーンショットを確認してください。バンドルのビルドが成功しても、表示が真っ白になることがあります。インライン化されていないアセット、CSP 違反、または遅延描画される分岐の実行時エラーがあると、ビルドは問題なく完了してもページは空白になります。

クイックスタート

ステップ 1:プロジェクトを初期化する

初期化スクリプトを実行して、新しい React プロジェクトを作成します。

bash scripts/init-artifact.sh <project-name>
cd <project-name>

以下が設定済みのプロジェクトが作成されます。

  • ✅ React + TypeScript(Vite 経由)
  • ✅ テーマシステムとして shadcn/ui を採用した Tailwind CSS 3.4.1
  • ✅ パスエイリアス(@/)を設定済み
  • ✅ 40 以上の shadcn/ui コンポーネントをプリインストール済み
  • ✅ Radix UI の依存関係をすべて含む
  • ✅ バンドル用に Parcel を設定済み(.parcelrc 経由)
  • ✅ Node 18 以降との互換性(Vite のバージョンを自動検出して固定)
ステップ 2:アーティファクトを開発する

アーティファクトを作成するには、生成されたファイルを編集します。ガイダンスについては、以下の 一般的な開発タスク を参照してください。

ステップ 3:単一の HTML ファイルにバンドルする

React アプリを単一の HTML アーティファクトにバンドルするには、次を実行します。

bash scripts/bundle-artifact.sh

bundle.html が作成されます。これは、すべての JavaScript、CSS、依存関係がインライン化された自己完結型のアーティファクトです。このファイルは、アーティファクトとしてエージェントとの会話で直接共有できます。

要件:プロジェクトのルートディレクトリに index.html が必要です。

スクリプトの処理内容:

  • バンドル用の依存関係(parcel、@parcel/config-default、parcel-resolver-tspaths、html-inline)をインストールする
  • パスエイリアスをサポートする .parcelrc 設定ファイルを作成する
  • Parcel でビルドする(ソースマップなし)
  • html-inline を使用して、すべてのアセットを単一の HTML にインライン化する
ステップ 4:アーティファクトをユーザーと共有する

最後に、バンドルされた HTML ファイルを会話でユーザーと共有し、アーティファクトとして表示できるようにします。

ステップ 5:アーティファクトのテスト/表示(任意)

注:この手順は完全に任意です。必要な場合、または依頼された場合にのみ実行してください。

アーティファクトのテスト/表示には、利用可能なツール(他の Skills や、Playwright、Puppeteer などの組み込みツールを含む)を使用します。一般に、アーティファクトをあらかじめテストするのは避けてください。完成したアーティファクトを表示するまでに遅延が生じるためです。依頼された場合や問題が発生した場合は、アーティファクトを提示した後にテストしてください。

参考資料

コメント