取り組みの背景 — なぜ今htmxなのか
近年のWebフロントエンド開発は、React・Next.js・Vue.jsといったSPAフレームワークが主流ですが、2026年に入ってもう一つの流れが静かに台頭しています。それが htmx です。
htmxは「Hypermedia As The Engine Of Application State(HATEOAS)」という設計思想にもとづき、JavaScriptをほぼ書かずにインタラクティブなUIを実現できるライブラリです。HTMLタグに属性を付与するだけで、AJAXリクエストやページ部分更新を可能にします。
AIチャットアプリケーションとの組み合わせが特に強力です。バックエンドがHTMLを返すだけでUIが更新されるため、状態管理の複雑さを大幅に削減できます。ここでは Antigravity IDE を使って、Python FastAPI + htmx + Gemini APIによるAIチャットアプリを最短で構築する方法を解説します。
htmxとハイパーメディアアーキテクチャ
htmxの根本的なアイデアは「HTMLをAPIレスポンスとして返す」ことです。従来のSPAではJSONを受け取り、Reactなどがそれをレンダリングします。htmxではサーバーが直接HTMLフラグメントを返し、ブラウザがそれをDOMに挿入します。
<!-- htmxを使ったシンプルなリクエスト例 -->
<form hx-post="/chat" hx-target="#chat-messages" hx-swap="beforeend">
<input type="text" name="message" placeholder="AIに質問する..." />
<button type="submit">送信</button>
</form>
<div id="chat-messages">
<!-- AIの応答がここに追加される -->
</div>hx-post="/chat"— フォーム送信時に/chatエンドポイントへPOSTリクエストhx-target="#chat-messages"— レスポンスの挿入先要素hx-swap="beforeend"— 既存コンテンツの末尾に追加
この3属性だけで、JavaScriptを一切書かずにAIの応答をリアルタイムで表示できます。
Antigravity IDEで開発環境を構築する
Antigravity IDEのターミナルから以下を実行して、プロジェクトを初期化します。
# プロジェクトディレクトリの作成
mkdir htmx-ai-chat && cd htmx-ai-chat
# Python仮想環境の作成
python3 -m venv .venv
source .venv/bin/activate
# 必要パッケージのインストール
pip install fastapi uvicorn jinja2 python-multipart google-generativeaiAntigravity IDEの補完機能は、requirements.txt を作成した時点でパッケージバージョンを自動提案してくれます。hx- 属性もHTMLファイル内で認識され、インテリセンスが効きます(AGENTS.mdにプロジェクト構成を記述することでより精度が上がります)。
ディレクトリ構成は以下の通りです。
htmx-ai-chat/
├── main.py # FastAPIアプリ本体
├── templates/
│ ├── base.html # ベーステンプレート
│ └── chat.html # チャット画面
├── static/
│ └── style.css # 最小限のスタイル
└── requirements.txt
FastAPI + htmxでAIチャットを実装する
main.py の実装です。ポイントはGemini APIをAntigravityのエージェントに実装させる点で、ビジネスロジックの記述に集中できます。
# main.py
import os
from fastapi import FastAPI, Form, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import google.generativeai as genai
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
# Gemini APIの設定
genai.configure(api_key=os.environ.get("GEMINI_API_KEY"))
model = genai.GenerativeModel("gemini-3-flash")
# チャット履歴を保持(実際のアプリではセッション管理を使用)
chat_history = []
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse("chat.html", {
"request": request,
"messages": chat_history
})
@app.post("/chat", response_class=HTMLResponse)
async def chat(request: Request, message: str = Form(...)):
"""htmxからのリクエストを受け取り、HTMLフラグメントを返す"""
# ユーザーメッセージを追加
chat_history.append({"role": "user", "content": message})
# Gemini APIでAI応答を生成
response = model.generate_content(message)
ai_reply = response.text
# AIメッセージを追加
chat_history.append({"role": "assistant", "content": ai_reply})
# HTMLフラグメントを返す(JavaScriptは不要)
return HTMLResponse(content=f"""
<div class="message user">
<strong>あなた:</strong> {message}
</div>
<div class="message assistant">
<strong>AI:</strong> {ai_reply}
</div>
""")<!-- templates/chat.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>AIチャット × htmx</title>
<!-- htmxをCDNから読み込む -->
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<div class="chat-container">
<h1>AIチャット(Gemini × htmx)</h1>
<!-- チャット履歴表示エリア -->
<div id="chat-messages">
{% for msg in messages %}
<div class="message {{ msg.role }}">
<strong>{{ "あなた" if msg.role == "user" else "AI" }}:</strong>
{{ msg.content }}
</div>
{% endfor %}
</div>
<!-- 送信フォーム(htmxで制御) -->
<form hx-post="/chat"
hx-target="#chat-messages"
hx-swap="beforeend"
hx-on::after-request="this.reset()">
<input type="text"
name="message"
placeholder="AIに質問してみましょう..."
required />
<button type="submit"
hx-indicator="#loading">送信</button>
</form>
<!-- ローディングインジケーター -->
<div id="loading" class="htmx-indicator">
AIが考え中...
</div>
</div>
</body>
</html>hx-on::after-request="this.reset()" により、送信後に入力フィールドを自動的にクリアします。これもJavaScriptなしで実現できます。
Gemini APIとの連携と環境変数管理
APIキーはAntigravityの.env管理機能を活用します。Antigravity IDEはプロジェクト設定画面から環境変数を安全に管理でき、AGENTS.mdへの記述でエージェントが自動的に .env ファイルを参照します。
# .envファイル(Antigravityの設定から自動生成)
GEMINI_API_KEY=YOUR_GEMINI_API_KEY
# 開発サーバーの起動
uvicorn main:app --reload --port 8000Antigravity IDEでは、環境変数のキー名を入力するだけで補完候補が表示されるため、タイポによるエラーを事前に防げます。
関連記事: Gemini APIカスタムAIツール構築ガイド
ストリーミング応答でUXを向上させる
Gemini APIはストリーミング応答をサポートしています。htmxのSSE(Server-Sent Events)拡張と組み合わせることで、AIの回答をリアルタイムに表示できます。
# ストリーミングエンドポイント(SSE版)
from fastapi.responses import StreamingResponse
@app.get("/chat/stream")
async def chat_stream(message: str):
"""Gemini APIのストリーミングをSSEで返す"""
def generate():
response = model.generate_content(message, stream=True)
for chunk in response:
if chunk.text:
# SSEフォーマット
yield f"data: {chunk.text}\n\n"
yield "data: [DONE]\n\n"
return StreamingResponse(generate(), media_type="text/event-stream")<!-- htmxのSSE拡張でストリーミング表示 -->
<script src="https://unpkg.com/htmx-ext-sse@2.2.1/sse.js"></script>
<div hx-ext="sse"
sse-connect="/chat/stream?message=こんにちは"
sse-swap="message">
<!-- ストリーミングテキストがここに逐次表示される -->
</div>さらに複雑なワークフロー自動化が必要な場合は、Temporal Workflow Engineとの連携ガイドも参考になります。
チャットUIのスタイリング
htmxの利点の一つは、CSSがそのまま使えることです。CSS-in-JSやビルドステップは不要で、シンプルなスタイルシートだけで整ったUIが作れます。
/* static/style.css */
.chat-container {
max-width: 720px;
margin: 2rem auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
#chat-messages {
min-height: 400px;
max-height: 600px;
overflow-y: auto;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
background: #fafafa;
}
.message {
padding: 0.75rem 1rem;
margin-bottom: 0.5rem;
border-radius: 8px;
line-height: 1.6;
}
.message.user {
background: #eff6ff;
border-left: 3px solid #3b82f6;
}
.message.assistant {
background: #f0fdf4;
border-left: 3px solid #22c55e;
}
/* htmxローディングインジケーター */
.htmx-indicator { display: none; color: #6b7280; font-style: italic; }
.htmx-request .htmx-indicator { display: block; }Antigravity IDEのCSSインテリセンスはクラス名や色の値を補完し、エージェントに「グラスモーフィズムテーマで再スタイリングして」と頼めばテンプレートごと自動更新してくれます。
Google Cloud Runへのデプロイ
ローカルで動作確認したら、Cloud Runでサーバーレスデプロイします。
# Dockerイメージのビルド&プッシュ
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/htmx-ai-chat
# Cloud Runへのデプロイ
gcloud run deploy htmx-ai-chat \
--image gcr.io/YOUR_PROJECT_ID/htmx-ai-chat \
--platform managed \
--region asia-northeast1 \
--allow-unauthenticated \
--set-env-vars GEMINI_API_KEY=YOUR_GEMINI_API_KEYAntigravity IDEはGCPとのデプロイ連携機能を持ち、「本番用Dockerfileを生成して」とエージェントに依頼するだけで、マルチステージビルドの最適化済みDockerfileが自動生成されます。
htmxページへのアニメーション追加には、Framer Motionによるウェブアニメーション連携ガイドも参考にしてください。ページ遷移やマイクロインタラクションをhtmxと組み合わせて実装できます。
まとめ
htmxとAntigravity IDEを組み合わせることで、JavaScriptのバンドルサイズを最小化しながら、インタラクティブなAIチャットアプリを効率よく構築できることがわかりましました。主なポイントを整理します。
hx-post/hx-target/hx-swapの3属性だけで非同期UIを実現- FastAPI + Jinja2テンプレートでHTMLフラグメントを返す設計がhtmxと相性抜群
- SSE拡張でGemini APIのストリーミングをリアルタイム表示
- Antigravity IDEのエージェントがバックエンドロジックを自動補完してくれるため開発速度が向上
- セキュリティ・環境変数管理もAntigravity IDEが支援
htmxはSPA至上主義への「シンプルな対抗軸」として、小〜中規模のWebアプリや社内ツール開発において非常に実用的な選択肢です。ぜひAntigravity IDEと組み合わせて、AI駆動のハイパーメディアアプリ開発を体験してみてください。