From cd32f0ae19eea736b50b26ad818e05de45c34dc4 Mon Sep 17 00:00:00 2001 From: reodesureodesu Date: Thu, 5 Mar 2026 07:26:52 +0900 Subject: [PATCH] Enhance lovable-style UI and add robust AI generation with Lovable provider --- README.md | 241 ++++++++ index.html | 972 ++++++++++++++++++++++++++++++ scripts/record_demo_playwright.py | 58 ++ scripts/verify_mcp_domain.sh | 61 ++ 4 files changed, 1332 insertions(+) create mode 100644 README.md create mode 100644 scripts/record_demo_playwright.py create mode 100755 scripts/verify_mcp_domain.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..f785c0c --- /dev/null +++ b/README.md @@ -0,0 +1,241 @@ +# TapApp Studio + +TapApp Studio は、**コードを書かずにタップ操作中心でUIプロトタイプを作成**できるシングルファイルWebアプリです。 +`index.html` をブラウザで開くだけで、要素追加・ドラッグ/リサイズ・スタイル編集・AI下書き生成・マルチデバイスプレビューが使えます。 + +--- + +## 目次 + +- [概要](#概要) +- [主な機能](#主な機能) +- [使い方](#使い方) +- [データ保存について](#データ保存について) +- [プライバシーポリシー](#プライバシーポリシー) +- [利用規約](#利用規約) +- [免責事項](#免責事項) +- [セキュリティ上の注意](#セキュリティ上の注意) +- [MCP サーバーURLとドメイン検証](#mcp-サーバーurlとドメイン検証) +- [デプロイ方法(Vercel)](#デプロイ方法vercel) +- [ライセンス](#ライセンス) + +--- + +## 概要 + +TapApp Studio は以下を目的としたプロトタイプツールです。 + +- 画面要素をタップ・ドラッグで直感的に配置 +- OpenAI / Hugging Face / Lovable AI(OpenAI互換)を使ったUI下書き生成 +- モバイル / タブレット / デスクトップのプレビュー確認 +- ローカル保存・再開・JSONエクスポート + +--- + +## 主な機能 + +- 要素追加(見出し / テキスト / ボタン / 入力欄 / カード) +- 直接操作(移動 / リサイズ / インライン編集) +- スタイル編集(色・枠線・角丸・余白・文字サイズ・透明度・回転) +- 整列 / 均等配置(左揃え、中央揃え、上揃え、横均等配置など) +- Undo / Redo +- タップ配置モード +- グリッド表示切替、吸着切替、ズーム +- マルチデバイスプレビュー +- AIレイアウト生成(OpenAI, Hugging Face, Lovable AI) +- `localStorage` 保存 / 再開 +- JSONエクスポート + +--- + +## 使い方 + +### 1. 起動 + +- `index.html` をブラウザで開く +- またはローカルサーバーを起動してアクセスする + +例: + +```bash +python -m http.server 4173 +``` + +ブラウザで `http://127.0.0.1:4173` を開いてください。 + +### 2. UIを作る + +1. 中央ツールバーから要素を追加 +2. 要素をドラッグして位置調整 +3. 右下ハンドルでサイズ調整 +4. 右パネルでスタイル・数値を微調整 +5. 必要に応じて整列 / 均等配置 / Undo / Redo を利用 + +### 3. AIで下書きを作る + +1. 左パネルで Provider(OpenAI / Hugging Face / Lovable AI)を選択 +2. 主要モデルプリセットを選択(必要ならカスタムモデル入力) +3. Lovable AIを選ぶ場合は OpenAI互換 Base URL を入力 +4. API Key と要件を入力 +5. 「AIで初期レイアウト生成」を押す + +※ AI生成はJSON抽出の再試行ロジックを実装しており、失敗時はテンプレートにフォールバックします。 + +### 4. プレビューする + +- 「プレビュー」ボタンで、Mobile / Tablet / Desktop の見え方を比較 + +### 5. 保存 / 再開 / エクスポート + +- 「保存」: `localStorage` に保存 +- 「再開」: 保存内容を復元 +- 「JSONエクスポート」: レイアウトJSONをダウンロード + +--- + +## データ保存について + +このアプリは主にブラウザの `localStorage` を利用します。 + +- レイアウト状態 +- 利用した Provider +- モデル名 +- API Key(入力した場合) + +**注意:** API Key を `localStorage` に保存したくない場合は、利用後にブラウザのローカルデータを削除してください。 + +--- + +## プライバシーポリシー + +TapApp Studio(以下「本アプリ」)は、以下の方針で情報を取り扱います。 + +1. **ローカル保存** + 本アプリは、編集状態や設定値をユーザーのブラウザ内(`localStorage`)へ保存します。 + +2. **外部APIへの送信** + ユーザーがAI生成機能を実行した場合、入力した要件テキストおよびAPI呼び出しに必要な情報は、選択した外部サービス(OpenAI または Hugging Face)へ送信されます。 + +3. **運営側サーバー収集** + 本リポジトリ版の構成では、独自バックエンドを経由しない限り、運営者が独自に入力データを収集する仕組みは含みません。 + +4. **第三者サービスの扱い** + 外部APIに関するデータ処理は、それぞれの提供元ポリシーに従います。利用前に必ず各社の規約・ポリシーをご確認ください。 + +5. **ユーザーの管理責任** + API Key・入力データ・保存データの管理はユーザー自身の責任で行ってください。 + +--- + +## 利用規約 + +本アプリを利用することで、以下に同意したものとみなします。 + +1. **自己責任での利用** + ユーザーは自己責任で本アプリを利用するものとします。 + +2. **禁止事項** + 法令違反、公序良俗違反、第三者権利侵害、外部API規約違反につながる利用を禁止します。 + +3. **外部サービス利用** + OpenAI / Hugging Face 等の外部サービスを利用する場合、当該サービスの利用規約を順守してください。 + +4. **知的財産** + 本アプリや本アプリを基にした成果物の権利関係は、適用される法令・契約・ライセンス条件に従います。 + +5. **規約変更** + 本規約は、必要に応じて予告なく変更される場合があります。 + +--- + +## 免責事項 + +- 本アプリは現状有姿(AS IS)で提供され、完全性・正確性・可用性を保証しません。 +- 本アプリ利用または利用不能により生じた損害について、作成者は責任を負いません。 +- AI生成結果の正確性・合法性・第三者権利非侵害は保証されません。 + +--- + +## セキュリティ上の注意 + +- 本番利用では API Key をクライアントに直接置かないでください。 +- 推奨構成: Vercel Functions などサーバー側経由でAI APIを呼び出す。 +- 公開端末で使用後は、ブラウザの保存データを削除してください。 + +--- + + +## デモ録画(開発者モード) + +Playwright を使って、**Web / iOS / Android** 向けのデモ動画を録画できます。 + +1. ローカルサーバー起動 + +```bash +python -m http.server 4173 +``` + +2. 別ターミナルで録画スクリプト実行 + +```bash +python scripts/record_demo_playwright.py +``` + +3. 出力動画(`artifacts/`) + +- `tapapp-demo-web.webm` +- `tapapp-demo-ios.webm` +- `tapapp-demo-android.webm` + +> iOS / Android は実機ではなく、ブラウザのモバイルエミュレーション設定で録画します。 + +--- + +## MCP サーバーURLとドメイン検証 + +### MCP サーバーURL + +本プロジェクトで利用する MCP サーバーURLは、運用環境に応じて設定してください。 + +- 推奨形式: `http(s):///mcp` +- 例: `http://example.com/mcp`(ドキュメント用サンプル) + +> 実運用では、MCP専用ドメイン(例: `mcp.your-domain.com`)を用意することを推奨します。 + +### ドメイン検証方法 + +`scripts/verify_mcp_domain.sh` で、以下をまとめて確認できます。 + +1. DNS解決 +2. TLS証明書(HTTPS) +3. HTTP到達性 + +実行例: + +```bash +./scripts/verify_mcp_domain.sh http://example.com/mcp +``` + +### 検証結果(このリポジトリでの実行例) + +- 対象URL: `http://example.com/mcp` +- DNS: 成功 +- TLS: スキップ(HTTP URLのため) +- HTTPステータス: `403`(到達性は確認) + +--- + +## デプロイ方法(Vercel) + +1. このリポジトリを GitHub に push +2. Vercel で New Project +3. 対象リポジトリを選択 +4. Framework Preset は `Other` +5. Deploy + +--- + +## ライセンス + +このリポジトリのライセンス方針に従ってください。 +ライセンスファイルが未整備の場合は、運用前に必ず明示してください。 diff --git a/index.html b/index.html index 8b13789..f4afb5e 100644 --- a/index.html +++ b/index.html @@ -1 +1,973 @@ + + + + + + TapApp Studio + + + +
+
+

TapApp Studio

+

Lovable風の柔らかいUI + タップ中心操作。AI生成の失敗率を下げるため再試行とJSON修復を追加。

+ +
+

1) AIで下書き

+ + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
見出し
+
テキスト
+
ボタン風
+
入力欄
+
カード
+
+ +
+
Undo
+
Redo
+
Grid
+
Snap
+
Preview
+
Zoom
+ + 100% +
+ +
+
+ +
+ +
+
+ +
+

3) 選択中の詳細編集

+

値はライブ反映。色は常時パレット表示。

+ + + + +
+
+ + +
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+ +
+
+ + +
+
+
+
+
+
+
+
+
+
+ + +
+
+ + + + + + + +
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+

ライブプレビュー

+
+
+
+

Mobile

+

Tablet

+

Desktop

+
+
+
+ + + + diff --git a/scripts/record_demo_playwright.py b/scripts/record_demo_playwright.py new file mode 100644 index 0000000..26b74d9 --- /dev/null +++ b/scripts/record_demo_playwright.py @@ -0,0 +1,58 @@ +from pathlib import Path +from playwright.sync_api import sync_playwright + +OUT = Path("artifacts") +OUT.mkdir(parents=True, exist_ok=True) + +TARGET = "http://127.0.0.1:4173" + +SCENARIOS = [ + {"name": "web", "viewport": {"width": 1366, "height": 768}}, + {"name": "ios", "viewport": {"width": 390, "height": 844}}, + {"name": "android", "viewport": {"width": 412, "height": 915}}, +] + + +def run_demo(page): + page.goto(TARGET, wait_until="networkidle") + page.wait_for_timeout(300) + + page.click('[data-add="heading"]') + page.click('[data-add="button"]') + page.click("#alignCenterBtn") + page.click("#alignMiddleBtn") + + page.click("#placeModeBtn") + box = page.locator("#phone").bounding_box() + if box: + page.select_option("#placeType", "card") + page.mouse.click(box["x"] + box["width"] * 0.52, box["y"] + box["height"] * 0.72) + page.click("#placeModeBtn") + + page.click("#previewBtn") + page.wait_for_timeout(700) + page.click("#closePreviewBtn") + + page.click("#toggleGridBtn") + page.click("#toggleSnapBtn") + page.wait_for_timeout(900) + + +with sync_playwright() as p: + browser = p.firefox.launch(headless=True) + + for s in SCENARIOS: + context = browser.new_context( + viewport=s["viewport"], + record_video_dir=str(OUT), + record_video_size=s["viewport"], + ) + page = context.new_page() + run_demo(page) + context.close() + + vids = sorted(OUT.glob("*.webm"), key=lambda x: x.stat().st_mtime) + if vids: + vids[-1].rename(OUT / f"tapapp-demo-{s['name']}.webm") + + browser.close() diff --git a/scripts/verify_mcp_domain.sh b/scripts/verify_mcp_domain.sh new file mode 100755 index 0000000..1ffea31 --- /dev/null +++ b/scripts/verify_mcp_domain.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +set -euo pipefail + +URL="${1:-}" +if [[ -z "$URL" ]]; then + echo "Usage: $0 " + exit 1 +fi + +PARSED="$(python - <<'PY' "$URL" +import sys +from urllib.parse import urlparse +u = urlparse(sys.argv[1]) +print((u.scheme or ""), (u.hostname or "")) +PY +)" +SCHEME="$(awk '{print $1}' <<<"$PARSED")" +HOST="$(awk '{print $2}' <<<"$PARSED")" + +if [[ -z "$HOST" ]]; then + echo "❌ Invalid URL: cannot parse host" + exit 1 +fi + +echo "MCP URL: $URL" +echo "Host: $HOST" + +echo "" +echo "[1/3] DNS resolution" +if getent hosts "$HOST" >/dev/null; then + getent hosts "$HOST" | head -n 1 + echo "✅ DNS resolved" +else + echo "❌ DNS resolution failed" + exit 1 +fi + +echo "" +echo "[2/3] TLS handshake" +if [[ "$SCHEME" == "https" ]]; then + if echo | openssl s_client -connect "$HOST:443" -servername "$HOST" 2>/dev/null | openssl x509 -noout -subject >/dev/null 2>&1; then + echo "✅ TLS certificate detected" + else + echo "⚠️ TLS check failed (network/cert issue)" + fi +else + echo "⚠️ TLS check skipped (scheme: $SCHEME)" +fi + +echo "" +echo "[3/3] HTTP reachability" +STATUS="$(curl -s -o /dev/null -w '%{http_code}' "$URL" || true)" +if [[ "$STATUS" =~ ^[1-5][0-9][0-9]$ ]] && [[ "$STATUS" != "000" ]]; then + echo "✅ HTTP response status: $STATUS" +else + echo "❌ No HTTP response" + exit 1 +fi + +echo "" +echo "Done. Domain verification completed."