自作テーマ
普段、Wordpressテーマ「swell」を使用してブログ運営をしていましたが自作テーマに切り替えることにしました。
もっとOpenAIのウェブサイトのような美しいデザインにしたいという願望があり、テーマを自作することで実現しようという試みです。
my-openai
Swellの開発者の方はエンジニア向けにテーマを無料公開されており、Swellの基本部分を実装したArcheを作成されています。
こちらをカスタマイズして、my-openaiを作成しました。
普段、Wordpressテーマ「swell」を使用してブログ運営をしていましたが自作テーマに切り替えることにしました。
もっとOpenAIのウェブサイトのような美しいデザインにしたいという願望があり、テーマを自作することで実現しようという試みです。
Swellの開発者の方はエンジニア向けにテーマを無料公開されており、Swellの基本部分を実装したArcheを作成されています。
こちらをカスタマイズして、my-openaiを作成しました。
今回、ウェブアプリケーションを作成する上で使用するAPIはGoogleが提供するGemini 1.5 Proです。
Gemini 1.5 Pro は次世代の大規模言語モデル(LLM)で、優れた自然言語生成能力を持っています。この記事では、Gemini 1.5 Pro APIを利用したシンプルなウェブアプリケーションを構築する手順を解説します。
Gemini 1.5 Pro API のエンドポイントや利用方法を確認します。
たとえば、以下のようなエンドポイントがあるかもしれません:
• POST /v1/models/gemini-1.5-pro/completions (テキスト生成用)
• POST /v1/models/gemini-1.5-pro/chat (チャット用)
mkdir my-gemini-app
cd my-gemini-app
npm init -y
npm install express axios dotenv
index.js ファイルを作成し、以下のコードを記述します。
require('dotenv').config(); // .env ファイルから環境変数を読み込む
const express = require('express');
const axios = require('axios');
const app = express();
const port = 3000;
// 環境変数から API キーを取得
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
const GEMINI_API_URL = 'https://api.gemini-platform.com/v1/models/gemini-1.5-pro/completions'; // 仮のURL
// JSON リクエストボディのパース
app.use(express.json());
// フロントエンド用の静的ファイルを配信
app.use(express.static('public'));
// 動作確認用エンドポイント
app.get('/', (req, res) => {
res.send('Hello from Gemini 1.5 Pro app!');
});
// 質問を受け付けて Gemini API に送信するエンドポイント
app.post('/ask', async (req, res) => {
try {
const userQuestion = req.body.question;
if (!userQuestion) {
return res.status(400).json({ error: 'No question provided' });
}
// Gemini 1.5 Pro API 呼び出し
const response = await axios.post(
GEMINI_API_URL,
{
prompt: userQuestion,
max_tokens: 100,
temperature: 0.7,
},
{
headers: {
'Authorization': `Bearer ${GEMINI_API_KEY}`,
'Content-Type': 'application/json',
},
}
);
const answer = response.data.choices[0].text.trim();
res.json({ answer });
} catch (error) {
console.error('--- Gemini API Error ---');
if (error.response) {
console.error('Status:', error.response.status);
console.error('Data:', error.response.data);
} else {
console.error('Message:', error.message);
}
res.status(500).json({ error: 'エラーが発生しました' });
}
});
// サーバー起動
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
public/index.html の作成
フロントエンドでGemini 1.5 Proに質問を送信する簡単なフォームを用意します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Gemini 1.5 Pro Chat App</title>
</head>
<body>
<h1>Gemini 1.5 Pro Chat App</h1>
<form id="questionForm">
<input type="text" id="questionInput" placeholder="質問を入力してください">
<button type="submit">送信</button>
</form>
<div id="answer"></div>
<script>
document.getElementById('questionForm').addEventListener('submit', async (e) => {
e.preventDefault();
const question = document.getElementById('questionInput').value;
const response = await fetch('/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question }),
});
const data = await response.json();
document.getElementById('answer').innerText = data.answer || data.error;
});
</script>
</body>
</html>
.env ファイルを作成し、以下のように記述します。
GEMINI_API_KEY=your-gemini-api-key
取得した Gemini APIキー をここに記載します。
node index.js
Gemini 1.5からAPI経由で回答が表示されます。
node.jsとExpressを使い、APIを使用したシンプルなアプリケーションを作成できました。
私はChatGPTやGeminiに質問しながら作成したので、かなり短時間で学習できました。
この機能をベースにしてさらに機能を追加することもできるので、ぜひチャレンジしてみてください。
AI技術は近年、驚くべきスピードで進化しています。特にOpenAIがGPT-4をリリースした2023年以降、多くのAIツールが登場し、さまざまな分野で活用されるようになりました。その中でも、Webサイトの構築に特化したAIツールは大きな注目を集めています。2025年現在、AIを活用したWebサイト構築は、技術に詳しくない人でも簡単に実現できるまでに進化しています。
今回のWebサイト構築では、以下の2つのAIツールを使用しました。
Image FXでは、サイトデザインのイメージ画像を生成しました。このツールでは、プロンプト(指示文)を入力するだけで、直感的で高品質なデザイン案を生成してくれます。私は最初、プロンプトを「Startup Company Website」と設定しましたが、希望通りの画像を得るために合計4回修正を行いました。最終的には、モダンで洗練された企業向けのウェブサイトデザインが完成しました。
次に、V0を使用して、Image FXで作成した画像を基にWebサイトのソースコードを生成しました。このツールの強みは、生成したデザインをそのまま忠実にHTMLやCSSコードへ変換できる点です。以下のプロンプトを使用しました:
「添付画像を忠実に再現したWEBサイトを作成してください。」
V0にはプレビュー機能が搭載されているため、生成されたコードを即座に実行して確認できます。デザインが想定通りに反映されているか、細部まで確認することができました。
画像デザインとは少し異なる部分もありますが、AIツールを使用したことで、わずか10分程度で簡単なWebサイトを構築することができました。ヘッダー、ロゴ、背景画像などの要素を追加することで、さらに完成度を高めることが可能です。
実際、これほど短時間でWebサイトを形にできるのはAIツールならではの魅力です。従来の手作業でのコーディングやデザイン作業と比較して、驚異的な効率性を実感しました。
ここ数年で流行りつつあるデザインに、「Glassmorphism」というものがあります。
このデザインは、リッチなウェブサイトやアプリの表現として使われていることが多いようです。
AppleのVision Pro のアプリはこのGlassmorphismのデザインが至る所で使用されており、独特の美しさを醸し出しています。
当サイトでもこの美しいデザインを取り入れたいと考えており、Wordpressのテーマ「SWELL」をカスタマイズして実装していきます。
早速ですが、SWELLのヘッダーのカスタマイズ方法を解説していきます。
(既に実装済みなので、手順のみ紹介していきます。)
テーマのカスタマイズですが、意外と簡単に実装することができます。
追加したCSSはこちらのサイトを参考にして、CSSのクラス名をSWELLで実装できるように変更しています。
ヘッダー以外のデザインも行いたい場合は以下のCSSのクラス名を変更して使用すると実装可能です!
/* Glassmorphism */
/* 背景 */
.bg {
width: 100%;
padding: 60px 30px;
display: flex;
align-items: center;
justify-content: center;
}
/* ガラス本体 */
.glass {
margin-top: 15px;
width: 100%;
max-width: 600px;
padding: 30px;
background-color: rgba(255, 255, 255, 0.04); /* 背景色 */
border: 1px solid rgba(255, 255, 255, 0.35); /* ボーダー */
border-right-color: rgba(255, 255, 255, 0.2);
border-bottom-color: rgba(255, 255, 255, 0.2);
border-radius: 15px;
-webkit-backdrop-filter: blur(20px); /* ぼかしエフェクト */
backdrop-filter: blur(15px);
}
/* ガラス内の要素 */
.glass {
text-align: center;
color: #fff;
font-family: "Heebo", sans-serif;
font-size: 20px;
font-weight: bold;
letter-spacing: 0.06em;
}
.glass p {
margin-top: 20px;
color: #fff;
font-size: 14px;
font-weight:Normal;
}
Glassmorphismのデザインをサイトに取り入れる際、難しいと思った点が2つあります。
このガラスデザインは密集した場所に複数設置してしまうと、やや鬱陶しいと感じてしまいます。
CSSで「border」の値を調整して、やや存在感を薄くすると問題が解決されるかもしれません。
ガラスデザイン特有の悩みですが、透明度を調整する際に薄くしすぎてしまうと自分がサイト内で際立たせたいものの存在感が無くなってしまいます。
これには十分注意して下さい。
詳細は省略しますが、当サイトのSELLlテーマをさらにカスタマイズしたのでカスタムCSSコードを貼っておきます。
<div class="bg"> <div class="glass"> <h1>IT LIFE</h1> <p>Let's start learning to code</p> </div> </div>
#post_slider .p-postList__item{
transform: perspective(0);
backface-visibility: hidden;
}
/*メインビジュアル下の空白削除 */
.top #content {
padding-top: 0 !important;
margin-bottom: 0;
}
#header {
margin: 0 auto;
}
.p-breadcrumb.-bg-on {
background-color: black;
}
/*ヘッダーフォント*/
.ttl {
font-family: "SF Pro JP", "SF Pro Text", "SF Pro Icons", "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", メイリオ, Meiryo, "MS Pゴシック", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-style: normal;
}
.ttl:hover {
color: #147CE5;
}
.c-gnav>.menu-item>a .ttl {
font-size: 13px;
}
/* Glassmorphism */
/* 背景 */
.bg {
width: 100%;
padding: 60px 30px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
/* ガラス本体 */
.glass {
margin-top: 15px;
width: 100%;
max-width: 600px;
padding: 30px;
background-color: rgba(255, 255, 255, ); /* 背景色 */
border-right-color: rgba(255, 255, 255, 0.2);
border-bottom-color: rgba(255, 255, 255, 0.2);
border-radius: 25px;
-webkit-backdrop-filter: blur(20px); /* ぼかしエフェクト */
backdrop-filter: blur(99px);
}
/* ガラス内の要素 */
.glass {
text-align: center;
color: #fff;
font-family: "Heebo", sans-serif;
font-size: 20px;
font-weight: bold;
letter-spacing: 0.06em;
}
.glass p {
margin-top: 20px;
color: #fff;
font-size: 14px;
font-weight:Normal;
}
/*.glass :: before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
filter: blur(3px);
Z-index: -1;
}*/
.bg {
content: ""; /* 必須 */
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 2.5rem;
background-color:hsla(0,100%,50%,1);
background-image:
radial-gradient(at 40% 20%, hsla(28,100%,74%,1) 0px, transparent 50%),
radial-gradient(at 80% 0%, hsla(189,100%,56%,1) 0px, transparent 50%),
radial-gradient(at 0% 50%, hsla(355,100%,93%,1) 0px, transparent 50%),
radial-gradient(at 80% 50%, hsla(340,100%,76%,1) 0px, transparent 50%),
radial-gradient(at 0% 100%, hsla(22,100%,77%,1) 0px, transparent 50%),
radial-gradient(at 80% 100%, hsla(242,100%,70%,1) 0px, transparent 50%),
radial-gradient(at 0% 0%, hsla(343,100%,76%,1) 0px, transparent 50%);
}
/*スマホサイズ メイン */
@media screen and (max-width:600px) {
.bg {
padding: 30px 30px;
border-radius: 2.0rem;
}
.glass {
margin-top: 0px;
}
}
/* ヘッダー */
.-txt .c-headLogo__link{
font-family: "SF Pro JP", "SF Pro Text", "SF Pro Icons", "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", メイリオ, Meiryo, "MS Pゴシック", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.l-header__inner{
background-color: rgba(50, 50, 50, 0.70); /* 背景色 */
border: 1.5px solid rgba(255, 255, 255, 0.08); /* ボーダー */
border-right-color: rgba(255, 255, 255, 0.2);
border-bottom-color: rgba(255, 255, 255, 0.2);
border-radius: 30px;
color: black;
-webkit-backdrop-filter: blur(20px); /* ぼかしエフェクト */
backdrop-filter: blur(5px);
position: fixed;/*fixedで固定*/
box-shadow: 0 1px 1px rgba(0,0,0,0.2);
}
/* ヘッダーホバーアニメーション */
.l-header__inner:hover {
/*background-color: rgba(255, 255, 255, 0.23);*/
transition: background-color 0.8s
}
/* ヘッダー追従 */
.l-header__inner {
width:100%;
color:white;
margin: 0 auto;
}
/*メニューカスタマイズ*/
.c-gnav .sub-menu {
font-size: 13px;
background-color: rgba(255, 255, 255, 0.65); /* 背景色 */
border: 1px solid rgba(255, 255, 255, 0.35); /* ボーダー */
border-radius: 8px;
}
/*ヘッダー幅*/
@media screen and (min-width:960px) {
/* ヘッダーメイン*/
.-txt .c-headLogo__link{
font-family: "SF Pro JP", "SF Pro Text", "SF Pro Icons", "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", メイリオ, Meiryo, "MS Pゴシック", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
font-style: normal;
}
.-series .l-header__logo {
padding: 0;
}
.l-header__inner {
margin: 9px;
}
.l-header__inner.l-container {
max-width: 900px;
margin-left: calc((100% - 900px) /2);
margin-right: calc((100% - 900px) /2);
height: 65px;
}
.c-gnav .sub-menu:before {
border-radius: 8px
}
}
@media screen and (max-width:720px) {
.l-header__inner.l-container {
max-width: 100%;
}
}
@media screen and (min-width:600px) {
.-txt .c-headLogo__link{
font-family: "SF Pro JP", "SF Pro Text", "SF Pro Icons", "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", メイリオ, Meiryo, "MS Pゴシック", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 20px;
font-style: normal;
}
}
/*moreボタン*/
a.btn_text:hover{
background-color: rgba(255, 255, 255, 0.20);
border: 0.25px solid rgba(255, 255, 255, 0.35);
}
button.c-fixBtn.c-plainBtn.hov-bg-main:{
background-color: rgba(255, 255, 255, 0.30);
border: 0.25px solid rgba(255, 255, 255, 0.35);
}
.c-fixBtn:hover {
background-color: rgba(255, 255, 255, 0.30);
}
button.c-tabList__button:hover{
background-color: rgba(255, 255, 255, 0.30);
border: 0.25px solid rgba(255, 255, 255, 0.35);
border-radius: top 8px;
}
.is-style-default>.c-tabList .c-tabList__button:hover, .is-style-default>.c-tabList .c-tabList__button[aria-selected=true] {
background-color: white;
border: 0.25px solid rgba(255, 255, 255, 0.35);
color: black;
border-radius: 8px;
}
.is-style-default>.c-tabList .c-tabList__button:hover, .is-style-default>.c-tabList .c-tabList__button:hover {
background-color: rgba(255, 255, 255, 0.30);
border: 0.25px solid rgba(255, 255, 255, 0.35);
color:white;
border-radius: top 8px;
}