次のような場合に使用: ダッシュボード、ウェブアプリ、ランディングページ、フォーム、管理ツールなど、ユーザーがブラウザで目にするUIを持つあらゆる機能を構築する場合 ユーザーインターフェースの設計に関する以下の内容をカバーしています: - JSX/React(Facebookが開発した作成方式)の慣例 - Twind/Tailwind(デザイン機能)を使ったスタイリング - Reactのバージョン固定 - ソースコード表示リンクの要件 - 回避すべき手法(テンプレート文字列によるHTML作成、外部アセット)
Use when building any val with a user interface — dashboards, web apps, landing pages, forms, admin tools, anything users see in a browser. Covers JSX/React conventions, Twind/Tailwind styling, React version pinning, the view-source link requirement, and what to avoid (template-string HTML, external assets).
UIを描画するvalについては、ユーザーが別の指定をしていない限り、.tsxファイルのReactコンポーネントで構築することを推奨します。templates/react-hono-starterテンプレートはこれに対応しており、ゼロから構築する代わりにremix_valで始めることができます。
マークアップ、スタイル、スクリプトは実ファイルに入れ、テンプレートリテラル文字列(例:new Response(\<html>...</html>`)`)での記述は避けてください。テンプレート文字列内のコードには、構文強調表示やリント検査、型チェック、コード審査の機能がありません。
.tsx — Reactコンポーネント、ロジックやインタラクティブな機能を含むUI.html — 静的なマークアップのみ.ts — サーバー側のコードとスクリプトUIは .tsxファイルでコンポーネント単位で構築します。1つの巨大なページを描画するのではなく、小さなコンポーネントを組み合わせます。
実行時にTailwindユーティリティクラスを適用するTwindを推奨します。ビルドステップは不要です。HTMLシェル(基本となるHTML)に以下のスクリプトを追加してください:
<script src="https://cdn.twind.style" crossorigin></script>
その後、JSXで直接Tailwindクラスを使用できます:
<div className="flex items-center gap-4 p-6 rounded-lg bg-white shadow">
<h1 className="text-2xl font-bold">Hello</h1>
</div>
ユーザーが別の指定をしていない限り、インラインの<style>タグ、CSSのJavaScriptオブジェクト、または別の.cssファイルは避けてください。
std/utilsのserveImmutableFileを使ってクライアント側のモジュールを配信してください。ブラウザはそれらを不変のキャッシュとして保存し、valを公開するとバージョンが更新されて自動的に無効化されます(完全なパターンはclient-side-jsスキルを参照)。immutableFileUrlでエントリーとファビコン(ブラウザのタブに表示されるアイコン)に時刻を記録する、キャッシュされないfrontend/root.tsxシェル(hono/jsx)を使用します:
// frontend/root.tsx — Root() HTMLシェル内:
<script src={immutableFileUrl("/frontend/index.tsx")} type="module" />
// index.ts:
app.get("/", (c) => c.html(Root()));
app.get("/__immutable/*", (c) => serveImmutableFile(c.req.path));
すべてのUI valは、ユーザーがそのソースコードを表示して再利用(リミックス)できるようにする必要があります。以下の2つの部分がどちらも必須です:
import { parseVal } from "https://esm.town/v/std/utils/index.ts";
app.get("/source", (c) => c.redirect(parseVal().links.self.val));
<a href="/source">view source</a>
一般的なエラーである「Cannot read properties of null (reading 'useState')」は、Reactの依存パッケージが異なるReactバージョンを読み込んでいることを意味します。React関連のすべてのインポートを18.2.0に固定してください:
import SomeLib from "https://esm.sh/some-lib?deps=react@18.2.0,react-dom@18.2.0";
外部画像やホストされているアセットで壊れる可能性があるものは使用しないでください。代わりに以下を推奨します:
ブラウザのエラーをval ログ(get_logsで確認可能)に送信するには、HTMLシェルに以下のスクリプトを含めてください:
<script src="https://esm.town/v/std/catch"></script>
UI valを編集した後、fetch_val_endpointを実行してページがエラーなく描画されることを確認してから、get_logsでブラウザ側のエラーがないかチェックしてください。どちらも確認しなければ、変更完了と報告しないでください。
For any val that renders a UI, prefer to build it with React components in .tsx files, unless the user states otherwise. The templates/react-hono-starter template is set up for this — start there with remix_val instead of building from scratch.
Put markup, styles, and scripts in real files — avoid template literal strings (e.g. new Response(\<html>...</html>`)`). Code in template strings has no syntax highlighting, no linting, no type checking, and is unreviewable.
.tsx — React/JSX components, any UI with logic or interactivity.html — purely static markup.ts — server code and scriptsBuild UI component by component in .tsx files. Compose small components rather than rendering one giant page.
Prefer Twind to apply Tailwind utility classes at runtime — no build step required. Add the script to your HTML shell:
<script src="https://cdn.twind.style" crossorigin></script>
Then use Tailwind classes directly in JSX:
<div className="flex items-center gap-4 p-6 rounded-lg bg-white shadow">
<h1 className="text-2xl font-bold">Hello</h1>
</div>
Avoid inline <style> tags, CSS-in-JS objects, or separate .css files, unless the user says otherwise.
Serve client modules with serveImmutableFile from std/utils — browsers cache
them immutably, and publishing bumps the val's version, which invalidates
automatically (full pattern: the client-side-js skill). A never-cached
frontend/root.tsx shell (hono/jsx) stamps the entry and favicon with
immutableFileUrl:
// frontend/root.tsx — in the Root() HTML shell:
<script src={immutableFileUrl("/frontend/index.tsx")} type="module" />
// index.ts:
app.get("/", (c) => c.html(Root()));
app.get("/__immutable/*", (c) => serveImmutableFile(c.req.path));
Every UI val should expose a way for users to see and remix its source. Both parts are required:
import { parseVal } from "https://esm.town/v/std/utils/index.ts";
app.get("/source", (c) => c.redirect(parseVal().links.self.val));
<a href="/source">view source</a>
A common error — "Cannot read properties of null (reading 'useState')" — means a React sub-dependency is loading a different React version. Pin all React-related imports to 18.2.0:
import SomeLib from "https://esm.sh/some-lib?deps=react@18.2.0,react-dom@18.2.0";
Do not use external images or hosted assets that may break. Prefer:
To send browser errors back to val logs (visible via get_logs), include this script in your HTML shell:
<script src="https://esm.town/v/std/catch"></script>
After editing a UI val, call fetch_val_endpoint to confirm the page renders without error, then check get_logs for any client-side errors. Don't report the change as done without both.
原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。