OpenSource-Hub

screenshot-to-code

アプリケーション

abi/screenshot-to-code

スクリーンショットやデザイン案をクリーンなコードに変換するAIツール。

概要

Screenshot-to-Code は AI モデルを活用して、スクリーンショット、デザインカンプ、画面録画を実行可能なコードに変換します。HTML、React、Vue などのフロントエンドフレームワークをサポートしています。スクリーンショットから実際の素材を抽出でき、複数のモデルプロバイダーに対応しています。プロジェクトには React フロントエンドと FastAPI バックエンドが含まれており、ローカルにデプロイすることも、公式ホスティングサービスを利用することもできます。

README プレビュー

# screenshot-to-code\n\nConvert screenshots, mockups, Figma designs, and screen recordings into clean, functional code using AI. The easiest way to try this is using the official, hosted product at screenshottocode.com →\n\n\nhttps://github.com/user-attachments/assets/ec08a5e6-9606-41c5-b03a-1bf47dfeba75\n\n\nSupported stacks:\n\n- HTML + Tailwind\n- HTML + CSS\n- React + Tailwind\n- Vue + Tailwind\n- Bootstrap\n- Ionic + Tailwind\n\nDefault AI models:\n\n- Gemini 3 Flash Preview and Gemini 3.1 Pro Preview - the best models\n- GPT-5.5 and GPT-5.4 Mini\n- Claude Opus 4.6, Claude Opus 4.8\n- z-image-turbo (using Replicate) for image generation\n\nSee the [Examples](#-examples) section below for more demos.\n\nScreenshot to Code also supports taking a screen recording of a website in action and turning that into a functional prototype.\n\n\n\n## 🛠 Getting Started\n\nChoose the path that fits what you want to do:\n\n- **Run locally:** best if you want to customize, self-host, or contribute.\n- **Use the hosted app:** the fastest way to try Screenshot to Code with no local setup. Open the hosted app →\n\nRunning locally requires API keys and a backend/frontend setup. The app has a React/Vite frontend and a FastAPI backend.\n\n### API keys\n\nYou need **at least one** model provider key (OpenAI, Anthropic, or Gemini).\n**Gemini and Replicate are strongly recommended for the best quality of\nscreenshot-to-code accuracy** — Gemini powers asset extraction (reusing the\nreal logos/images from your screenshot) and Replicate powers image\ngeneration, background removal, and image editing. Adding all four keys gives\nthe best results and lets you compare multiple models per generation.\n\n| Key | Required? | What it unlocks |\n|-----|-----------|-----------------|\n| `OPENAI_API_KEY` | One of these three | GPT code-gen variants (GPT-5.5, GPT-5.4 Mini) |\n| `ANTHROPIC_API_KEY` | One of these three | Claude code-gen variants (Opus 5, Opus 4.8, Fable 5, Sonnet 4.6) |\n| `GEMINI_AP

FAQ (5)

トラブル対応
Starlette WebSocketのクラッシュを修正する方法:異常終了コード1006後のRuntimeError "Unexpected ASGI message 'websocket.close'"

issue #599 の修正を含む最新リリースにアップグレードしてください。一時的な回避策として、以前のメジャーバージョンにダウングレードしてください。コードにパッチを適用するには、Starlette から WebSocketDisconnect をインポートし、WebSocketCommunicator.close() と throw_error() がすでに閉じられた状態を処理するようにします。例:

from starlette.websockets import WebSocketDisconnect

try:
    await ws_comm.close()
except (
    ConnectionClosedOK,
    ConnectionClosedError,
    WebSocketDisconnect,
    RuntimeError,
):
    pass

throw_error() にも同じ例外処理を適用してください。これにより、uvicorn がすでに接続を閉じた後に finally ブロックが別の websocket.close ASGI メッセージを送信するのを防ぎます。このクラッシュは Python 3.11、uvicorn 0.25.0、Starlette 0.41.3、websockets 14.1 で確認されました。

参照 Issue #599
トラブル対応
ストリーミングで例外がスローされた場合に AsyncAnthropic のコネクションプールの枯渇やコネクションリークを修正するにはどうすればよいですか?

クライアントのライフサイクルを try/finally で囲み、ストリーミングやセッションの初期化が失敗した場合でも close() が実行されるようにします:

client = AsyncAnthropic(api_key=api_key)
try:
    # ストリーミング / セッションロジック
    ...
finally:
    await client.close()

あるいは、クライアントを非同期コンテキストマネージャーとして使用します:

async with AsyncAnthropic(api_key=api_key) as client:
    # ストリーミングロジック
    ...

同じパターンを AsyncOpenAI と stream_claude_response、stream_claude_response_native の両方にも適用してください。クリーンアップを行わないと、例外が発生した際に HTTP 接続が開いたまま残り、長時間稼働するサービスではコネクションプールを使い果たす可能性があります。

参照 Issue #534
トラブル対応
screenshot-to-code のコード生成が OpenAI の model not found、無効な API key、または rate limit エラーで失敗する問題は、どうすれば修正できますか?

まずバックエンドのログを確認して、OpenAIのエラーの正確な原因を特定してください:

docker compose logs backend --tail=100
# または
docker logs <container_id>

よくある修正方法:

1. **APIキーが無効または未設定の場合:** 環境変数または .env ファイルに OPENAI_API_KEY が正しく設定されていることを確認してから、コンテナを再起動してください。
2. **モデルが見つからない、または利用できない場合:** generate_code.py で gpt-4o-2024-11-20 のような日付付きのモデルが固定指定されている場合は、OpenAIアカウントで利用可能なモデル(gpt-4o や gpt-4 など)に変更してください。
3. **レート制限またはアカウントの制限がある場合:** OpenAIの請求/使用状況ダッシュボードを確認し、リクエストの頻度を下げるか、レート制限がリセットされるまで待ってください。
4. **設定変更後の再起動:** docker compose down && docker compose up --build を実行してください。

恒久的な修正としては、generate_code.py に明示的なOpenAI APIのエラーハンドリングを追加し、認証、レート制限、モデル未検出のエラーがサイレントに失敗するのではなく、きちんと表面化されるようにしてください。

参照 Issue #506
トラブル対応
Poetry が typing-extensions 4.12.2 のインストールに失敗し、"All attempts to connect to pypi.org failed" というエラーが表示されるのはなぜですか?

これは typing-extensions パッケージの問題ではなく、ネットワーク/DNS/プロキシの問題です。PowerShell で、まず接続をテストしてください:

Resolve-DnsName pypi.org
Invoke-WebRequest https://pypi.org/simple/ -UseBasicParsing
poetry install -v

ローカルプロキシを経由している場合は、Poetry を実行する前に設定してください(ポートはご自身のプロキシポートに置き換えてください):

$env:HTTP_PROXY = "http://127.0.0.1:7890"
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
poetry install

ネットワーク上で PyPI がブロックされている場合は、一時的にミラーを使用してください:

$env:POETRY_PYPI_MIRROR_URL = "https://pypi.tuna.tsinghua.edu.cn/simple/"
poetry install

また、VPN/ファイアウォールソフトウェアを無効にするか再設定してから、poetry install を再実行してみてください。

参照 Issue #520
トラブル対応
OpenAI SDK を使用した際に発生する DeepSeek API エラー "Failed to deserialize the JSON body into target type: messages[1] ... ChatCompletionRequestContent" の修正方法

この 422 エラーは、messages[1].content が DeepSeek が受け付けない形式になっていることを意味します。DeepSeek は OpenAI 互換ですが、OpenAI のマルチモーダルなコンテンツパート配列を受け付けない場合があります。メッセージの content は代わりにプレーンテキスト文字列として送信してください。

失敗しているメッセージを確認してください:

import json
print(json.dumps(params["messages"][1], ensure_ascii=False, indent=2))

API を呼び出す前にコンテンツ配列をテキストに変換してください:

def normalize_deepseek_messages(messages):
    for message in messages:
        content = message.get("content")

        if isinstance(content, list):
            message["content"] = "".join(
                part.get("text", "")
                for part in content
                if isinstance(part, dict) and part.get("type") == "text"
            )
        elif content is None:
            message["content"] = ""

    return messages

params["messages"] = normalize_deepseek_messages(params["messages"])
stream = await client.chat.completions.create(**params)

また、image_url や input_audio などのサポートされていないパートは削除し、DeepSeek のテキスト/チャット形式のみを使用してください。エージェントフレームワークを使用している場合は、ビジョン/マルチモーダルのメッセージフォーマットを無効にするか、プレーンテキストの OpenAI 互換メッセージを強制してください。

参照 Issue #488