🌌

GingaUI—LLMを活用し文脈に合わせたテーマを生成するUIコンポーネントライブラリ—

2025/03/09に公開

本ライブラリは NICT のセキュリティイノベーター育成プログラム「SecHack365」にて開発を進めました。この場を借りまして、トレーナー、アシスタント及び事務局の皆様に感謝を申し上げます。

https://github.com/newt239/ginga-ui

GingaUI」は LLM を活用しウェブサイトのデザインテーマを自動で生成する機能を備えた UI コンポーネントライブラリです。React で構築されており、Next.js などのフレームワークと組み合わせて利用できます。

どんなもの?

https://x.com/newt239/status/1847925274207457716

以下のポートフォリオサイトに PoC を実装しているので、ヘッダー右上のボタンからぜひお試しください。

https://newt239.dev/

一言で言うと、ウェブサイトの文章にふさわしいテーマを自動で生成する機能を備えた UI コンポーネントライブラリです。

先に書いておくと、テーマというのは配色やフォント、角丸の大きさなどのスタイル部分を指しており、レイアウトやコンポーネントの配置等の画面設計に関しては対象としていません。

導入方法

GingaUI は npm からインストール後、起点となるページで CSS ファイルをインポートし、表示したい場所にコンポーネントを配置するだけで、簡単に導入できます。

import { ThemeClient } from "@ginga-ui/core";

const client = new ThemeClient({
  clientType: "openai",
  apiKey: "YOUR_OPENAI_API_KEY",
});

LLM によるテーマ生成機能を利用する場合、まずサービスプロバイダーから API キーを取得します。本ライブラリでは現在 OpenAI, Gemini, Anthropic に対応しています。

その後テーマを生成するクラスをインスタンス化し、テーマを生成したいページでキーワードとともに呼び出します。

import { Button } from "@ginga-ui/core";

export default async function Home() {
  const { CSSCode } = await client.generateTheme("fairy tale");
  return (
    <div>
      <style>{CSSCode}</style>
      <Button>Button</Button>
    </div>
  );
}

セキュリティ上の問題があるためサーバーサイドでの実行を推奨しています。サンプルコードも Next.js の App Router における実装例で、CSSCode という変数を style タグで囲って出力することができます。

下図はこのライブラリを利用して作ったブログサイトの例です。MicroCMS と連携して記事ページごとにテーマを生成できるブログサイトのテンプレートを、newt-sechack/ginga-ui-next-templateで公開中です。

https://github.com/newt-sechack/ginga-ui-next-template

サイト訪問者に新たな体験を提供

AI にデザインを考えさせるという点においてv0とアプローチが似ていますが、GingaUI が目指す方向性はこれとは全く異なります。本ライブラリは「ユーザーに」新たな体験を届けることをコンセプトとしており、画面設計をはじめとする実装部分に関しては開発者が行うべきだと考えています。

極端な言い方をすれば、開発者はウェブサイトのテーマ選択において責任を負わず、すべて各ページに表示するコンテンツに基づいて自動で生成するということです。

具体的なユースケースとして、「ユーザーが投稿するコンテンツが主となる記事投稿サイトや SNS」や「一定のランダム性や AI の可能性を一種の芸術として取り入れたいウェブサイト」を考えています。

より具体的には note のように様々な人が様々なテーマで投稿する UGC 系のサイトを考えていて、サイト全体で統一した配色を提供するのではなく、レイアウトは保ったうえで記事ごとに独自のカラーを出すことで、方もウン車の閲覧体験が向上するのでは?と考えています。

一方で「ブランドサイトやコーポレートサイトなど、ウェブサイトにアクセスしたときの印象が変わると困るもの」や「インターネットに慣れていない人が多くアクセスするウェブサイト」には、このライブラリは向かなそうです。

テーマ生成機能の仕組み

システムプロンプトとして「Web ページの文章が与えられるので、以下に挙げる CSS 変数に最もふさわしい値を考えてください」といった指示を入れ、ユーザーからの文章とともに、JSON 形式で応答するよう設定したうえでリクエストを送ります。

Response
{
  "--color-primary": "#f3f5d7",
  "--color-secondary": "#8cc63f",
  "--color-background": "#4a4a4a",
  "--font-family": "sans-serif",
  "--size-radius": "16px",
  "--width-border": "2px"
}

あらかじめ用意する CSS のコードには CSS 変数を利用し、LLM からの応答をもとに、デフォルトで適用しているスタイルを上書きしています。

button.css
.button {
  font-family: var(--font-family);
  color: var(--color-background);
  background-color: var(--color-primary-9);
  border-radius: calc(var(--size-radius) * 0.5);
}

生成させている変数は現在次の 6 つのみですが、実際のウェブサイトではより多くの色が使われています。このため background-color との間で機械的にカラースケールを生成し、場所に応じてこの色レベルを変えることで、LLM に生成させる変数の数を削減しています。

Name Description Default Value
--color-primary Accent color #1677ff
--color-secondary Main text color #000000
--color-background Background color #ffffff
--width-border Border width 2px
--size-radius Border radius 16px
--font-family Font family sans-serif

コントラストを意図的に下げようとする攻撃

LLM のプロンプトに応じてウェブサイトのデザインが変わる機能には、意図的に可読性を下げようとする攻撃が行われる余地が存在します。

例えば「文字色と背景色に同じ色を使って」といったプロンプトを送ることで、テキストが読めなくなるようなデザインを生成させることができてしまいます。

GingaUI では一定以上のコントラストを確保する機能を搭載しました。具体的にはchroma-jsというライブラリを利用し、一定のコントラストを確保しています。

技術的な話

リポジトリでは pnpm workspace と Turporepo を使ったモノレポの構成を採用しています。

パッケージはコンポーネント単位で分割されており、packages/componentsにそれぞれのコンポーネントが格納されています。

tsup を使ってビルドし、Chansets でリリース管理を行っています。

アクセシブルな UI パターンを実装するため、Adobe が提供している React Aria というライブラリを取り入れています。デザインが提供されていないヘッドレスなライブラリであるため、GingaUI ではこれをベースにスタイルや独自の機能を実装しています。

むすびにかえて

GingaUI は開発が始まったばかりのライブラリであり、まだまだコンポーネント数や機能が不足しています。今後もほそぼそと開発を進めていく予定なので、興味を持っていただけた方がいれば、ぜひ Star や Contribution をいただけますと幸いです。

また、方向性や未来性についてのフィードバックや議論も歓迎します。

https://github.com/newt239/ginga-ui

Discussion