makereal(tldraw)を試してみる

はじめに

こんにちは、エンジニアのクロ(@kro96_xr)です。

先日以下のようなポストが流れてきました。

言葉にするならワイヤーフレームからHTMLを生成できるツールでしょうか。
元々Miroライクなホワイトボードアプリとしてtldrawがあり、それにOpenAIのGPT-4Vを組み合わせたツールとしてmakerealが公開されたようです。

github.com

github.com

私自身メインはサーバサイドであり、フロントエンドは得意ではないので早速使ってみることにしました。

なお、https://makereal.tldraw.com/にアクセスすればブラウザ上でも使用できますが、リポジトリも公開されているのでローカル上で試してみます。

使い方

環境構築に必要な作業は以下の通りです。

  1. リポジトリのクローン
  2. OpenAIのAPIキー取得
  3. プロジェクトを立ち上げる
  4. APIキーを設定
  5. 図を描く
  6. 生成!

リポジトリのクローン

Gitに慣れている方であれば説明不要だと思いますが、https://github.com/tldraw/make-realにアクセスしてリポジトリをクローンします。

===以下ChatGPTで作成===

  1. まず、コンピュータにGitがインストールされていることを確認します。インストールされていない場合は、Gitの公式サイトからダウンロードしてインストールしてください。
  2. コマンドラインまたはターミナルを開きます。
  3. 次のコマンドを使用して、tldraw/make-realリポジトリをクローンします。
git clone https://github.com/tldraw/make-real.git

クローンが完了したら、次のコマンドで新しく作成されたディレクトリに移動します。

cd make-real

===ここまでChatGPTで作成===

不明点などがあれば公式のリファレンスもあわせてご覧ください

docs.github.com

OpenAIのAPIキー取得

GPT-4Vを使用するためにOpenAIのAPIキーが必要になります。

OpenAIのサービスにログインの上、API KeysにアクセスしてAPIキーを生成しましょう。
Create new secret keyをクリックし、必要情報を入力するとAPIキーを生成できます。発行したAPIキーは後ほど使うので安全な場所にコピペしておきましょう。

また、APIの使用は有料なので、Payment Methodからクレジットカードを登録しておきましょう。

プロジェクトを立ち上げる

ここまでできたらクローンしたプロジェクトを立ち上げます。
手順はREADMEにも書いてある通りです。

Node.jsをインストールしていない場合はまずインストールする必要があります。
公式サイトからインストーラーをダウンロードしてインストールするか、nvmを使ってインストールしましょう。
nvmの使い方は割愛しますので、各自検索をお願いします。

公式

Node.js

Windowsの場合

GitHub - coreybutler/nvm-windows: A node.js version management utility for Windows. Ironically written in Go.

Mac/Linuxの場合

GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions

Node.jsをインストールしたら、クローンしたディレクトリ内に移動して以下のコマンドを実行し、依存するパッケージをインストールします。

npm i

パッケージのインストールが正常に終了したら、サービスを立ち上げます。

npm run dev

正常に立ち上がったらhttp://localhost:3000/にアクセスするとホワイトボードが表示されます。

APIキーを設定する

画面中央下にYour OpenAI API Keyと書かれた入力欄があるので、先に発行しておいたAPIキーをコピペします。

ここまでで環境構築は完了です。

図を描く

いよいよ実際に図を描いていきます。
tldrawの機能で描いてもいいですし、スクショをペーストして作ってもらうことも可能です

ちょうどMiroで適当に書いたECサイトのトップページみたいなものが手元にあったのでペーストしてみます。

生成

図を描き終えたらGPT-4Vに渡したい範囲を選択して、右上のMake Realボタンを押すだけです。

うーん、それぞれの要素の配置はあっていますが、ちょっと違いますね。
特にバナーは完全に消えてヘッダとくっついているように見えます。

どうやらテキストでの補足もできるようなので試してみます。

指示を英語にした影響か、サイト内の文章も英語になりましたが、カルーセルも実装してくれました。

ただ、このままではECサイトっぽくないのでもう少し雑な指示にチャレンジしてみます。

基本的な要素は変わらず、バナーより下の部分のテキストと画像サイズが変わりましたね。
たしかに元のデザインはサムネイルが小さすぎるので、良い変更だと思います。

こうなってくるとサムネイルに画像を追加したいですね。
(greatの綴りを間違えていることにスクショ撮り終わってから気づきました)

図とテキストの指示を組み合わせてここまで作ることができました。
一旦今回はこのくらいにしておきます。

HTLMの確認

生成したサイトのHTMLはクリップボードにコピーすることができます。

今回生成したコードが以下になります。
内部の画像はunsplash.comから取得しているようで、商用利用も無料なので安心ですね。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>E-commerce Site</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        /* Additional styles if needed */
        .carousel-indicator {
            transition: background-color 0.3s;
        }
        .carousel-indicator.active {
            background-color: #4B5563; /* Gray-600 */
        }
    </style>
</head>
<body class="bg-white text-gray-800">
    <div class="container mx-auto px-4 py-8">
        <header class="text-white text-center p-6 mb-6" style="background-color: #1E40AF;">
            <h1 class="text-3xl font-bold">Your Shop</h1>
        </header>

        <section class="mb-6">
            <div id="carousel" class="relative">
                <div class="flex justify-center space-x-2 mb-4">
                    <span class="carousel-indicator h-3 w-3 bg-gray-300 rounded-full cursor-pointer active"></span>
                    <span class="carousel-indicator h-3 w-3 bg-gray-300 rounded-full cursor-pointer"></span>
                    <span class="carousel-indicator h-3 w-3 bg-gray-300 rounded-full cursor-pointer"></span>
                </div>
                <div class="flex overflow-hidden">
                    <img src="https://source.unsplash.com/random/800x300?sig=1" alt="Banner 1" class="block w-full">
                    <img src="https://source.unsplash.com/random/800x300?sig=2" alt="Banner 2" class="block w-full">
                    <img src="https://source.unsplash.com/random/800x300?sig=3" alt="Banner 3" class="block w-full">
                </div>
            </div>
        </section>

        <section class="mb-6">
            <h2 class="text-2xl font-semibold text-center mb-4">Featured Products</h2>
            <div class="grid grid-cols-3 gap-4">
                <!-- Placeholder for product thumbnails -->
                <img src="https://source.unsplash.com/random/200x200?product,1" alt="Product 1" class="w-full h-48 rounded-lg">
                <img src="https://source.unsplash.com/random/200x200?product,2" alt="Product 2" class="w-full h-48 rounded-lg">
                <img src="https://source.unsplash.com/random/200x200?product,3" alt="Product 3" class="w-full h-48 rounded-lg">
            </div>
        </section>

        <section>
            <h2 class="text-2xl font-semibold text-center mb-4">Latest Arrivals</h2>
            <div class="grid grid-cols-3 gap-4">
                <!-- Placeholder for product thumbnails -->
                <img src="https://source.unsplash.com/random/200x200?product,4" alt="Product 4" class="w-full h-48 rounded-lg">
                <img src="https://source.unsplash.com/random/200x200?product,5" alt="Product 5" class="w-full h-48 rounded-lg">
                <img src="https://source.unsplash.com/random/200x200?product,6" alt="Product 6" class="w-full h-48 rounded-lg">
            </div>
        </section>
    </div>

    <script>
        // Simple carousel functionality
        const indicators = document.querySelectorAll('.carousel-indicator');
        const slides = document.querySelectorAll('#carousel img');
        let currentSlide = 0;

        indicators.forEach((indicator, i) => {
            indicator.addEventListener('click', () => {
                indicators[currentSlide].classList.remove('active');
                slides[currentSlide].classList.add('hidden');
                currentSlide = i;
                slides[currentSlide].classList.remove('hidden');
                indicator.classList.add('active');
            });
        });

        // Auto-rotate slides every 5 seconds
        setInterval(() => {
            indicators[currentSlide].classList.remove('active');
            slides[currentSlide].classList.add('hidden');
            currentSlide = (currentSlide + 1) % slides.length;
            slides[currentSlide].classList.remove('hidden');
            indicators[currentSlide].classList.add('active');
        }, 5000);
    </script>
</body>
</html>

おわりに

以上、簡単に触ってみましたが、ワイヤーフレームとテキストからそれらしいものが生成できたので、モック制作や個別のコンポーネント制作の時などに役立ちそうかなと思いました。

一方でチーム開発や運用を見据えるとデザインシステムの構築なども必要であり、この生成AIで開発が完結することはないと思います。ただ、AIの進歩は凄まじいので1ヶ月後はわかりませんね。

いずれにせようまく活用して業務効率化していきたいですね!