create-html-app について
Create HTML Appは、Hubbleで動作する単一HTMLファイルのインタラクティブな画面を作るためのスキルです。ツール、ダッシュボード、小規模アプリを開発する人向けで、サンドボックス環境とWorkspaceのMarkdownファイルを扱うAPIを利用します。
主な機能
- 01単一のHTMLファイルで画面を構築
- 02Hubble提供のAlpineとTailwindを使用
- 03サンドボックス化されたiframeで実行
- 04Files API経由でWorkspaceファイルにアクセス
- 05Markdownファイルの表示や作成
活用シーン
- 01フォルダー内で動くインタラクティブツールの構築
- 02Workspaceファイルを読むダッシュボードの作成
- 03Markdownを閲覧して開くインターフェースの作成
MCP 対応
入力には、このスキルとMCPの関係について記載されていません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bholmesdev/ hubble-skills --skill create-html-appインストール後、Claude Code で/create-html-appを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/buttons.mdfiles-api.mdforms.mdlists-and-empty-states.mdradio-selects.mdtabs.md詳細
HTML アプリの作成
Hubble HTML アプリは、フォルダー内にある .html ファイルで、Hubble が自己完結型のインタラクティブな UI として実行します。開くと、メインコンテンツパネルにアプリが表示されます。フォルダー内に単一の .html ファイルを作成して、ツール、ダッシュボード、アプリなど、あらゆるインタラクティブな体験を構築できます。
Markdown ファイル内に HTML アプリをインラインで埋め込む方法については、create-embed を参照してください。
ランタイム
Hubble がアプリのランタイムを提供します。以下のグローバル変数がすでに使用可能であることを前提とした、プレーンな HTML を記述してください。
hubbleAlpine- Tailwind browser v4
- Hubble のテーマトークン
デフォルトでは Alpine と Tailwind を使用してください。依存関係の <script> タグを追加したり、パッケージファイル、ロックファイル、node_modules を用意したりしないでください。
HTML アプリはサンドボックス化された iframe で実行されます。Hubble では以下が許可されています。
allow-scripts:Alpine、Tailwind browser、Hubble ランタイムを実行できます。allow-forms:@submit.preventなどの Alpine ハンドラーと組み合わせることで、ネイティブ HTML フォームのセマンティクスが機能します。
Hubble では以下は許可されていません。
allow-same-origin:アプリのオリジンは不透明なままであり、アプリのオリジンに属するストレージや Cookie、同一オリジンアクセスは使用できません。allow-top-navigation:アプリからデスクトップアプリのフレームに移動することはできません。allow-popups/allow-popups-to-escape-sandbox:サンドボックス化されていないポップアップウィンドウを開くことはできません。allow-downloads:アプリから直接ダウンロードを開始することはできません。allow-modals:モーダル形式のブラウザーダイアログは使用できません。
Files API
アプリは、ファイルシステムに直接アクセスするのではなく、非同期ブローカーである hubble.files を通じてワークスペース内のファイルにアクセスします。すべてのパスはワークスペース相対で、Markdown ファイルを指します。
await hubble.files.list("todos/*.md")
// → [{ name, path, modified_at, size }], sorted by path
await hubble.files.read("notes/today.md")
// → { path, body, properties }
await hubble.files.open("notes/today.md")
// → { path }, navigates the editor to the file
await hubble.files.create({ path, body, properties, open })
// → { path, body, properties }
await hubble.files.update(path, { body, properties })
// → { path, body, properties }, patch
await hubble.files.remove("notes/today.md")
// → { path }
メソッドは失敗時に例外をスローします。各メソッドには safe* 版があります。データ形式、パッチのセマンティクス、エラー処理については、Files API を参照してください。
テンプレート
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Folder files</title>
</head>
<body class="m-0 bg-background p-3 font-sans text-foreground">
<main
class="grid gap-3 rounded-md border border-border bg-card p-3 text-card-foreground"
x-data="{
files: [],
error: '',
async init() {
try {
this.files = await hubble.files.list('**/*.md')
} catch (error) {
this.error = error.message || 'Could not load files'
}
},
}"
>
<header class="flex items-center justify-between gap-3">
<h1 class="m-0 text-base font-semibold">Folder files</h1>
<span class="text-sm text-muted-foreground" x-text="`${files.length} files`"></span>
</header>
<p class="m-0 text-sm text-muted-foreground" x-show="!error && files.length === 0">
Loading files...
</p>
<p class="m-0 text-sm text-destructive" x-show="error" x-text="error"></p>
<ul class="m-0 grid list-none gap-2 p-0" x-show="!error && files.length > 0">
<template x-for="file in files" :key="file.path">
<li class="rounded-sm border border-border bg-background px-3 py-2">
<span class="text-sm font-medium" x-text="file.path"></span>
</li>
</template>
</ul>
</main>
</body>
</html>
ロジックの構成
フラグ、カウンター、現在のタブなど、単純な状態にはインラインの x-data を使用してもかまいません。非同期ローダー、複数のメソッド、計算ロジックなど、より複雑な処理では、<script> 内で Alpine.data() コンポーネントを登録し、名前で参照してください。
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('fileList', () => ({
files: [],
error: '',
async init() {
try {
this.files = await hubble.files.list('**/*.md')
} catch (error) {
this.error = error.message || 'Could not load files'
}
},
}))
})
</script>
<main x-data="fileList">…</main>
複雑なインライン式を避けるメリットは次のとおりです。
- Alpine は
x-dataを単一の式として解析します。アロー関数、オブジェクトメソッド、</>/&を含む複数行の本体は、HTML エスケープされたり、誤って解析されたりして、気づきにくい「Alpine Expression Error」を引き起こします。 - ロジックを属性文字列の中ではなく、シンタックスハイライトと通常の引用符が使える、実際の JavaScript 内に記述できます。
- コンポーネントは再利用およびテストが可能で、マークアップも読みやすく保てます。
Alpine が DOM を走査する前にコンポーネントが存在するよう、alpine:init 内で登録してください。
ネイティブな見た目
アプリがネイティブな印象になるよう、Tailwind クラスを通じて Hubble のトークンを使用してください。
- サーフェス:
bg-background、bg-card、bg-popover - テキスト:
text-foreground、text-muted-foreground、text-card-foreground - ボーダー/リング:
border-border、border-input、ring-ring、focus-visible:ring-ring - アクション:
bg-primary text-primary-foreground、bg-secondary text-secondary-foreground - 状態:
hover:bg-accent、bg-selected text-selected-foreground
余白はコンパクトに保ってください:gap-2、gap-3、p-2、p-3、px-3、py-2。コントロールには rounded-sm または rounded-md を使用してください。
ユーザーからテーマに沿ったビジュアルを求められない限り、場当たり的な配色、大きすぎるカード、ヒーローレイアウト、装飾的なグラデーションは避けてください。
リファレンス
必要なパターンだけを参照してください。