見出し画像

PMのAI日記


はじめに

 転職活動中のある日、『LOST』という海外ドラマを見ていました。乗客を載せた飛行機が無人島に墜落し、生存者同士が助け合いながら化け物と戦い、サバイブする、そんな話です。その時あることに気がつきました。どんなドラマにも登場する職業があるなと。

それは「医者」でした。では、なぜ「医者」はそんなに登場機会が多いのでしょうか?それは、人の命が大切なものであり、この世界において「価値」があるからだと思います。『LOST』の中でも、ジャックという医者を中心として物語が進行します。

私は当時20代半ばでしたので、今から医者を目指そうというのは現実的には想像できませんでした。ただ『LOST』には、もう1人脇役的ながらも活躍する人物がいて、その名はサイードと言う、アラブ系のエンジニアでした。無人島の中で、怪我した人を治せるのは貴重な「価値」ですが、外界と通信ができるというのもまた「価値」だったのです。Huluというストリーミングサービスでその作品を見ていたのもあり、TSUTAYAにわざわざ貸し借りの為に移動しなくても良くなり、かつ価格も下がるという、その「価値」に魅力を感じていました。

シェイクスピアの名言に「この世は舞台、人はみな役者」というのがありますが、どうせ一度きりの人生ならば、この日本列島でサイードとして生きることで活躍できるかもしれない、そう思い立って、ITエンジニアの道を歩むこととなります。

就職氷河期の真っ只中、かつ第二新卒という条件でITエンジニアに転職した為、大企業などは箸にも棒にもかからず、派遣主体の下請け会社からのスタートとなり、上京します。私はサイードを目指していたので、遅れてスタートした分1時間早く出社したり、毎週末ITの勉強をしました。でも3年経っても給与は努力の反映など無情にもなく、このままの人生で良いのか?と無力感を感じるようになっていきました。

これはおそらく派遣という日本の見えない身分制度で冷遇されているだけではないか?と疑問に思うようになったのと、当時スタートアップが流行しはじめていたので、たまたま出向先の隣にあった会社に、腕試しがてらお昼休憩時に面接に向かったところ、物流管理者の正社員として即採用となりました。

それもそのはず。人が次々と辞めていくような、とんでもない仕事量が待っていました。まさにカオス。ダンボールの開け方も知らず、商品をカッターで傷つけてほったらかしになっていたり、ロケーション管理もグチャグチャで、入荷した商品が見つからず出荷できないというのが日常茶飯事。アルバイトも新人社員の言うことは聞かないし、そもそも外国人が多いので言葉が通じない。物流の現場でITの知識を持っていることは珍しく、ロジカルに優先度をつけて問題を一つ一つ解決し、私はマネージャーへと昇格しました。給与もいつのまにか以前の倍になっていました。

ただまた3年くらいも経つと、自分が井の中の蛙ということに気付かされるようになります。ヘッドハンティングされた社員は、私の倍の給与レンジでした。スタートアップの初期からコミットしてきた人間にとってはやっていられないという思いが募り、徐々に腐っていきました。退職ラッシュが社内で始まります。私もその流れの中で、ITx物流の知見を生かして、大企業への転職を成功させ、物流ロボットの世界へとキャリアを移します。

こう言ってはなんですが、スタートアップに比べてびっくりするくらい生ぬるい環境だったように思います。それでも前より待遇が良い。世の中は、稼ぐだけなら過去のキャリアの美しさやコミュニケーションの方がずっと重要なのだと身に沁みて感じました。ただ同時に、成長していない自分に苛立ちを覚えるようになります。このままでは終われない、挑戦したい。そして、フリーランスとして独立し、現在に至ります。

様々なプロジェクトに参画しました。物流のリアルな現場経験に加え、システム開発の全工程及び全ポジションを経験したと言っても過言ではないと思います。そんな中で他業界にも当てはまるビジネスルールやフローを学習しました。ビジネスは、売上さえ上がれば勝てる単純なゲームではありません。コストを抑え、利益を出す。利益を最大化していく、その流れを作る必要があります。そして、オンラインシフトしていく現代でその流れの基軸となるのは、間違いなくホームページ(以降HP)だと考えます。

本著では「PMのAI日記」と題し、プロダクトマネージャー(PM
)である私が、オンラインで存在感(プレゼンス)のある「集客できるホームページの作り方」をログ形式で紹介していきます。実際に行ったログの形を取りますので、途中トラブルにも遭遇します。それを一つ一つ生成AIを使って解決していくことで、最新技術の使用方法が皆様に伝わればという思いで書きました。また、ビジネスで活かせるホームページでなければ意味がないとも思い、IT技術の説明だけではなく、マーケティング要素をふんだんに散りばめました。

ただし、マーケティングは私のメインドメインではない為、下記youtubeを参照してエッセンスを取り込み、「ビジネスで使えるオンラインプレゼンスの高い」ホームページ(以降HP)を制作したいと思います。

あなたのHPの「オンラインプレゼンス」を向上させることに貢献できるのであれば、この上ない喜びです。


0.システムの本質は龍が如く

 いきなり開発に入っていく前に、システムの本質について話をさせてください。システムはよく難しいと言われますが、それはある意味本当で、ある意味嘘です。何がその難しさを感じさせるのでしょうか?それはおそらく横文字の専門用語かもしれません。でも、私がよく感じるのは、全てが「擬似的」であるということこそが、そう思わせてしまっている一番強い要因のように思います。一時期「仮想化」という言葉が流行りましたが、まさにコンピュータの世界は仮想化のオンパレードです。

例えば、ゴミ箱。きっとあなたのデスクトップに存在することでしょう。では、あなたのそのコンピュータ内に物理的に存在するのでしょうか?それは、当然Noです。穿った言葉の取り方をすれば、ストレージには物理的に存在するということになりますが、ゴミ箱そのものが存在するわけでは決してありません。これと同じことが、クラウドにも言えます。クラウドサーバーは本当に雲の上に存在するのでしょうか?この答えも、当然Noです。どこかの倉庫の中にサーバーが存在し、その中でコンピュータを細かく分けて割り当て管理しているにすぎません。したがって、クラウドも嘘であり、ゴミ箱も嘘です。ただ、便宜上そう伝えると人に伝わりやすいので、あくまでそう呼称しているにすぎないのです。

物事の本質というのはどんなにファンシーに見えたり聞こえたりしても、実態は泥臭いというのが真理のように思います。ITを学ぶ上でこの点を抑えることが最初のステップです。どんなに難しい物言いをしても、あくまでそれは疑似的であり、実態を理解すると高尚そうに言うのがあくまで上手いだけであって、とてつもなく簡素な話をしていることに気付くようになります。

そして、もう3つ重要な概念があります。その一つは「プログラムは一方向に電気のように走る」ということです。だから、chatGPTは即時返答ができるし、ITによって業務スピードが劇的に向上するのも電気が流れるスピードで情報処理をするからです。その一方で、「目に見えない鉄砲を作るようなもの」ということも忘れないでいていただきいのです。システムで「あぁしたい、こうしたい」と自由に要求を並べてみてもそれを実装する時間は、その言葉の比べ物にならないくらい、何百倍の時間がかかる。それはなぜでしょうか?それは例えば鉄砲を作ってと言って、2〜3日ですぐ作れるのか?というのと、ほぼ同義と捉えていただきたいのです。ただ、一度作ってしまえば、それはとてつもない強力な武器となり、このビジネスという戦場で生き残る上で、あなたの助けとなります。

そして、最後に最も核となる概念である「関数」を理解することで、あなたもコンピュータとお友達になれると言っても過言ではありません。最も有名かつ便利な関数は「VLOOKUP」関数でしょうか?私がエンジニアに成りたての時、これは魔法だと感動しました。尚、関数の「関」は、「箱」を意味していて、この「箱」に変数を与えることによって、結果が変わります。眠たくなってしまったでしょうか?でも、先に伝えた通り、物事の本質は単純です。安心してください。箱にどんな値を入れるのか、「変わる」ので、変数というだけの話です。

「VLOOKUP」は完成された一つの「鉄砲」です。インプットする値が4つという特殊な「関数」ですが、実際にあなたのエクセルやスプレッドシートで入力して確かめてみると理解が進みますが、ここでは下記のようにデータが存在した時の「VLOOKUP」の使用例を一つ示しておきます。

vlookup例

「VLOOKUP」内にカンマで区切っているのが、4つに分かれているのに気づくでしょうか?「A2・A:B・2・0」で分かれています。

本例では、A2の値(りんご)をA列とB列から探して、見つかったらその2番目の値を持ってきてと依頼している関数となります(最後の0はおまじないと思っていただいて構いません)。答えはそう、「赤」です。これが何になるの?と不思議に思う方もいるかもしれません。ですが、これは英語で言うと「This is a pen.」を伝えているようなものだと思っていただきたいのです。それをまず知ることによって、コンピュータの基本の「キ」が伝わり、応用が効く知識となります。

まとめると、システムは「擬似的」で「関数」という「鉄砲」の形で「電気」を放ち、新しい解を返す。これは押し並べて、自然言語で解を返すchatGPTも「関数」の一種であることが伝わるでしょうか?

それはまるで我々に刻まれたDNAの形のように、龍が如く螺旋を描き、人類を高次へと導きます。

1.海外テンプレート活用方法

 時短開発する為、今回はenvatoelementsという海外のテンプレート屋さんのソースを利用します(先の表現で言うと、「鉄砲」を仕入れて、改造します)。理由は、英語圏の方が開発人口が多く、選択できるテンプレートが豊富であるからです。そして、日本企業が手を出さない可能性が高くなる為、他社と被るリスクが下がり、「オンラインプレゼンス」を保持できるからです。

envatoelementsのWeb Templatesを使用

今回はサンプルとして、「react」と「nextjs」という技術を使用して行いますが、もしご自身の得意な技術があれば、適宜envatoelementsの検索窓に別キーワードを入れて、ご活用されることをオススメいたします。また、私の利用しているOSがmacとなる為、以降の写真もmacのキャプチャとなりますこと、あらかじめご容赦いただけますと幸いです。

Vieというテンプレートを選択
自分の名前にチェックを入れるとダウンロード可能
zipを解凍
3つのフォルダの内、13を選択
yarnコマンド実行時

nodeバージョンはv16.18.0を使用しています。yarnコマンド実行後は、yarn devコマンドでローカルの立ち上げができるようになります。

yarn dev後のページ

このテンプレートは上の写真のように、それぞれのデザインでURLが異なり、そのままでは活用できませんので、不要部分をコメントアウトしていきます。

MainContentをコメントアウト
ヘッダー部のみの表示になることを確認
homepage/home2-light/

以下、デフォルトでこのページが開くように調整していきます。
"homepage/home2-light/"のソースがどこにあるか不明なので、grepコマンドを使って探索します(grepコマンドの使用方法が不明な方は検索して調べてみてください。windowsだとfindコマンドになります)。
事前準備をすれば、このような手法を説明する必要はないのですが、「現場で使えるリアルな情報」が価値を持つと思いますので、壁にぶつかり、都度どう乗り越えるのかを具体的に記載していきます。

grep -lr "Digital Consulting" 

./src./src/components/Headers/Header3.jsx
./src/components/Headers/Header2.jsx

"Digital Consulting"で検索すると、2つのファイルに絞られました。どちらが使用されているのか不明なので、中のファイルを"①"と入力し、識別します。

Header2.jsx
①と出てる!
mainContent.jsxをコピーし、mainContent2.jsxを作成
mainContent2.jsxに向き先を変更
Header2のコンポーネントをインポート
不要となったヘッダーをコメントアウト
反映完了

これによって、トップページが完成しました。ただし、メッセージが英語なのと、背景色が黒となってしまったので、写真も含めて調整していきます。

cssをdark→lightに変更
日本語化し、写真を差し替え

"About Us"となっていたところは、「お問い合わせ」に変更しました。これは先のyoutubeのマーケティング講師りゅう先生が、「メディアからの問い合わせ先を載せること」が最重要だと仰っていたので、まず最も重要なアクションにつながりやすいようにする考えに基づいています。

もちろんテンプレートを利活用していますので、モバイル対応もデフォルトで行われます。

モバイル画面

ただ、このままだと「お問い合わせ」ボタンはリンクにすぎませんので、実際にその機能を追加していきます。

ContactFormをインポート
お問い合わせページを追加

同様に英語を日本語化し、twitterなど古いサイトだと思われないように一次的にコメントアウトします(必要であればXに変更してください)。りゅう先生曰く、ホームページは更新されているのがマーケティングにおいても重要要素となるそうです。逆に更新されていないと信用を獲得できないと考えると、月1のアップデートはマスト要件とのことでした。
それから、cssを強制変更した為、入力文字の色が白となってしまった為、入力しても表示されないので、これを黒へと変更します。

"option + command + i"を同時に押下することによって、Chromeブラウザでは、使用されているcssの確認を取ることができます。

css調査時

#fffとlight.cssになってしまっていますので、これを#000に変更します。

お問い合わせフォーム更新後

続いて、先ほどのお問い合わせボタンを押下した時に、この画面にスクロールするように変更します。

スクロール変更

Linkタグからaタグに変更し、href内も#contact-formとすることによって、id=contact-formの地点に、ボタン押下でトップページ内で画面遷移するようにします。

ここでりゅう先生のポイントは、世の中のほとんどの会社が自分の会社が「取材される」って思ってなかったりするそうです。なので、お問い合わせフォームには必ず「取材」を追加する必要があり、そうしないと、取材を受け付けしているかどうかもわからなくなってしまうので、常にウェルカムな状態を作っていないと勿体無いとのことでした(コピーしても使用できるようにContactForm.jsxを下記のように変更しました)。

import React, { useState } from "react";
//= Components
import Split from "@/components/Common/Split";
//= Static Data
import contentFormData from "@/data/contact-form.json";

function ContactForm({ theme }) {
  const [inquiryType, setInquiryType] = useState("general");
  return (
    <section className="contact section-padding">
      <div className="container">
        <div className="row">
          <div className="col-lg-6">
            <div className="form md-mb50">
              <h4 className="fw-700 color-font mb-50">お問い合わせフォーム</h4>

              <form id="contact-form">
                <div className="messages"></div>

                <div className="controls">
                  <div className="form-group">
                    <div className="radio-buttons">
                      <label>
                        <input
                          type="radio"
                          value="general"
                          checked={inquiryType === "general"}
                          onChange={() => setInquiryType("general")}
                        />
                        一般的なお問い合わせ
                      </label>
                      <label>
                        <input
                          type="radio"
                          value="interview"
                          checked={inquiryType === "interview"}
                          onChange={() => setInquiryType("interview")}
                        />
                        取材
                      </label>
                      <label>
                        <input
                          type="radio"
                          value="other"
                          checked={inquiryType === "other"}
                          onChange={() => setInquiryType("other")}
                        />
                        その他
                      </label>
                    </div>
                  </div>

2.お問い合わせフォーム実装方法

 次にこのお問い合わせフォームも機能しなければ意味がありませんので、newtというサービスを使って、お問い合わせがあった時にメール通知する機能を実装します。これによって、自動返信もできますし、開発工数も大幅削減することができますの。尚、設定方法詳細は、以下を参照してください。

マーケティング視点では、ホームページを作成する目的は1〜2に絞った方が良いので、「メディアの実績掲載と取引先を増やすこと」と定めます。なので、採用要素やLP的な要素は排除し、文言をリニューアルします。

キャッチコピーを調整
ビジネスアライアンス(協業)に変更

3.メディア実績欄の実装方法

 「メディアの実績掲載」が必要となってきますので、下記のポートフォリオを組み込んで、改造することにします。

ポートフォリオ

以前やったのと同様に上のページの"Past Projects"を持つソースをgrepします。Portfolioを発見しました。

grep -lr "Past Projects" ./src

./src/components/Works/WorksStyle2.jsx
./src/components/Works/Works5.jsx
./src/components/Works/Works2.jsx
./src/components/Works/Works3.jsx
./src/components/Portfolio/index.jsx

code ./src/components/Portfolio/index.jsx
Portfolio.jsxを追加
Portfolio.jsx追加後

画像が大きくなってしまいました。システム開発していると、こういうトラブルが連続的に発生します。こういったリアルなところも含めて本書ではご紹介し、皆様のトラブルシューティングにも応用いただけますと幸いです。

grep -lr "Portfolio" ./src

./src/app/(light)/homepage/home2-light/page.js
./src/app/(light)/homepage/home4-light/page.js
./src/app/(mobile-app-dark)/mobile-app/portfolio-dark/page.js
./src/app/(mobile-app-light)/mobile-app/portfolio-light/page.js
./src/app/(dark)/homepage/home4-dark/page.js
./src/app/(dark)/homepage/home2-dark/page.js
./src/components/Mobile-app/Navbar.jsx
./src/components/Common/Navbar.jsx
./src/components/Common/NavbarFullMenu.jsx
./src/components/Works/WorksStyle2.jsx
./src/components/Works/Works5.jsx
./src/components/Works/Works3.jsx
./src/components/Portfolio/index.jsx
./src/components/Demos/MainContent2.jsx
./src/components/Demos/Services.jsx

code ./src/app/(light)/homepage/home2-light/page.js

上記の"./src/app/(light)/homepage/home2-light/page.js"のディレクトリから呼ばれている時には、問題が発生していませんので、その差分を調査していきます。

grid={3}でコールされている!
コピー&ペースト
ポートフォリオ引用に成功

また例によって英語になってしまっていますので修正していくのに加え、メディア実績がまだホームページ開発中の現在は当然存在しませんので、ニュース1〜6に名称変更していきます。ちなみに、jsxタグにカーソルを合わせ、「fn +F12」を押下することによって、visual studioのテキストエディターでは、そのソースに遷移してくれる便利機能がありますので、ぜひぜひご活用ください。

カーソル当てて「fn +F12」
最新ニュース①
最新ニュース②

デフォルトの写真がおしゃれなので、それっぽくなってきましたね。SNS全盛のこの時代でも、ホームページでメディア実績を定期的に更新し、歴史を積み重ねることが、信頼獲得につながる「最強のツール」となるそうです。また、プレスリリースはPR Timesなど出稿で3~5万円で行うことができるそうで、三冠バッジは30~50万円で購入できるそうです。また、150万~200万円の予算があれば、テレビや雑誌にPRして実績を買うこともできると説明されていました。

三冠バッジ例

ここまで、トップページ用に「キャッチコピー・お問い合わせフォーム・メディア実績」のページを開発してきました。あとは、「基本情報・事業概要・IR・採用情報・Q&A」などのページを作成するのが効果的だそうですが、目的は必ず絞るべきということを同時にりゅう先生は、ご主張されていました。先程申し上げた通り、今回は「メディアの実績掲載と取引先を増やすこと」と定めましたので、次に「基本情報・事業概要」のページを追加することにします。

Footer.jsxを追加
フッター

不要部分を削除し、アップデートします。

基本情報アップデート後

4.ロゴの実装方法


 vieというロゴが、このビジネスを想起させないので、変更します。Canvaを使います。

Canva

上のメニューの"Resize & Magic Switch"を押下することによって、500 x 284にリサイズできます。また、右上の"Share"ボタンを押すことでダウンロードができ、その時に背景透過を選択することができます。
ロゴつながりでナビゲーションバーがまだ存在しないので、追加します。

Navbar追加
Navbar追加後
黒バージョンのロゴも追加


ロゴ変更後

ロゴは変更されたものの、メニューを開いてクリックすると、画面遷移するようになってしまっていますので、現時点ではコメントアウトしておき、後でページが全て揃った時に調整します。ちなみにコメントアウトは範囲にカーソルを当てた状態で、「command + /」を押下することによっても可能です。

メニューのコメントアウト

5.縦型動画の実装方法

 基本情報は「住所・メールアドレス・電話番号」などのみと思っていましたが、ちょっと違いました。りゅう先生の動画をもう一度見直したところ、動画による代表挨拶や企業理念のこともでした。動画は最近流行りの縦型にした方が良いようです。<Video />タグを追加していきます。

<Video />タグ追加
<Video />タグ追加後の画面

3k+のハッピークライアントと14k+の成功プロジェクトというラベルがありますが、「代表挨拶や企業理念」では数字部分は不要ですので、コメントアウトします。

文言更新後

私自身が現在個人事業主であって、DAO的な形式で働くような形であったので、あえてDAO理念としました。DAOとは何かというと、非中央集権的組織のことで、トップ不在で、個々人が自立して一つのプロジェクトに取り組む組織のことです。私が代表であり、実質上はチームのトップなのですが、会社組織よりは序列がないので、時流に乗ってDAO理念を創造します。

再生ボタンを押すと、どうやら縦型動画ではないので、これが変更できないかトライしてみますが、やり方が不明なので、ChatGPTとBardに聞いてみました。Bardの方が良い回答をしてくれたので、以下に引用します。

この React コンポーネントは YouTube と Vimeo の埋め込み動画を表示するもので、現状では縦型動画に直接的に変更することはできません。しかし、いくつかの方法で縦型動画に対応させることは可能です。

1. 縦型動画の埋め込み URL を用意する

YouTube や Vimeo では、縦型動画専用の埋め込みコードを提供している場合もあります。チャンネルやビデオIDに合わせて、縦型動画用の埋め込みコードを取得するように getYoutubeUrl と getVimeoUrl の関数を更新しましょう。

2. iframe のアスペクト比を調整する

iframe の width と height 属性を調整することで、縦型動画に適したアスペクト比にすることができます。例えば、9:16 の縦型動画であれば width="230" と height="460" で表示できます。

3. 外側のコンテナを調整する

.modal-video-movie-wrap の CSS スタイルを更新し、縦型動画に合わせて高さを確保し、枠内に収まるように調整しましょう。必要に応じて余白やパディングも調整してください。

4. ライブラリを利用する

React には、縦型動画を再生するためのライブラリも存在します。 react-player などを検討してみましょう。これらのライブラリは、適切なアスペクト比やレスポンシブレイアウトを自動的に調整してくれる機能がある場合があります。

いずれの方法を選ぶかは、ご使用の動画の種類やプレゼンテーションの意図などに応じて検討してください。

また、コメントで縦型動画の例や具体的にどのような表示を目指すのか教えていただければ、より具体的なアドバイスもできるかもしれません。

Bard回答

一番簡単そうな「2. iframe のアスペクト比を調整する」をトライしてみましたが、何も変化がありませんでした。

縦型動画用に変更
レスポンシブで確認

以前説明したように、"option + command + i"を同時に押下することによって、Chromeブラウザでは、使用されているcssの確認を取ることができます。この開発モードはそれに加えて、画面のサイズを調整することができます。これによって、縦型動画対応できているか識別できるようになります。

続いて、「3. 外側のコンテナを調整する」にチャレンジしてみましょう。

grep -lr "modal-video-movie-wrap" ./src

./src/styles/modal-video.css
./src/components/Common/ModalVideo.jsx

code ./src/styles/modal-video.css
3箇所に"modal-video-movie-wrap"があることを発見

cssをヒューマンリードせずに、bardに修正してもらうように依頼しましょう。

提供されたコードに基づき、縦型動画に対応させるための修正案を以下に示します。

1. modal-video-movie-wrap のスタイル調整:padding-bottom: 56.25%; を削除します。これは横長動画用のアスペクト比の設定なので、縦型動画の場合は不要です。
必要に応じて、高さを指定するか、親要素の縦方向の伸びに追従するように height: 100%; を設定します。


2. iframe のスタイル調整:height: 100%; を設定することで、親要素の高さを埋めるように調整します。


3. modal-video-close.modal-video-movie-wrap のスタイル:このセレクターは不要です。.modal-video-movie-wrap のスタイルのみで十分です。


修正後のコードは以下のような形になります。

Bard回答
.modal-video-body {
  max-width: 1100px;
  width: 100%;
  height: 100%;
  margin: 0 auto;
  display: table;
}

.modal-video-inner {
  position: relative;
  display: table-cell;
  vertical-align: middle;
  width: 100%;
  height: 100%;
}

.modal-video-movie-wrap {
  width: 100%;
  height: 100%; /* 縦方向の伸びに追従させる場合 */
  position: relative;
  background-color: var(--modal-bg-color);
  animation-timing-function: var(--animation-function);
  animation-duration: var(--animation-speed);
  animation-name: modal-video-inner;
  transform: translate(0, 0);
  transition: transform var(--animation-speed) var(--animation-function);
}

.modal-video-movie-wrap iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

このコードで、縦型動画の埋め込みに対応し、 iframe が親要素の高さを埋めるように表示されるはずです。

さらに、より微調整が必要な場合は、具体的にどのような表示を望んでいるのか、どのサイズの縦型動画に対応させたいのかなど、情報を教えていただければ、より詳しいアドバイスができるかもしれません。

Bard回答

大体それっぽい回答を返してきて、うまくいかないケースがほとんどですので、何の期待もせずに言う通り修正していきます。

css調整後

やはり何も変更されないので、「4. ライブラリを利用する」に移行します。yarn add react-playerをターミナルで打ちます。

yarn add react-playerの結果

成功しました。追加したライブラリを使用して、使用するようにbardにコード修正を依頼し、結果を反映します。

ただの屍のようだ

流石に2~4をやればと思いましたが、難しいようです。最後の「1. 縦型動画の埋め込み URL を用意する」に希望を託します。
下記のサイトを参考にして、埋め込みを行いました。

ショート動画の埋込コードに変更
縦型表示成功

現在私はマーケティング学習に力を入れており、マーケティングの著名人ばかりご紹介しているのは、ご容赦いただければと思います(笑)。結果、Bardは嘘はついてはいなくて、「1. 縦型動画の埋め込み URL を用意する」と「3. 外側のコンテナを調整する」ことによって実現できましたので、「4. ライブラリを利用する」を元に戻しておきます(2は不要です)。

yarn remove react-player
yarn remove v1.22.17
warning ../../../package.json: No license field
[1/2] 🗑  Removing module react-player...
[2/2] 🔨  Regenerating lockfile and installing missing dependencies...
warning "eslint-config-next > @typescript-eslint/parser > @typescript-eslint/typescript-estree > ts-api-utils@1.0.3" has unmet peer dependency "typescript@>=4.2.0".
success Uninstalled packages.
✨  Done in 1.10s.

6.高齢化社会とCSS調整方法

 「基本情報」を出す枠組は揃いましたので、あとは「事業概要」のページを追加します。事業概要サンプルページは元々それっぽいのがありますので、それを加えて日本語に変更していきます。

事業概要サンプルページ
Servicesタグを引用
MainContent2.jsxを更新
事業概要サンプルページ日本語化中

最後のアイコンがグラフィックになっていて、どうも事業概要のパズルに当てはまらないので、変更することにします。

pe-7s-paint-bucketを利用

pe-7s-paint-bucketで検索してところ、以下のサイトが表示されました。

アイコン変更後

これで「事業概要」もOKかと思いきや、高齢化社会の昨今、文字が薄いことは、実はあまり好まれません。センスという自己満足は一旦置いておいて、マーケティング視点で顧客に伝わりやすいデザインにしていく必要があります。
3回目ですが、そろそろ開発コンソールの開き方は、覚えましたでしょうか?大丈夫です。何度でも復習をしましょう。

"option + command + i"を同時に押下することによって、Chromeブラウザでは、使用されているcssの確認を取ることができます。

先述
配色確認

そしたら次は何をするか?そう、grepですね。

grep -lr "#888" ./ 

.//public/css/light.css

code .//public/css/light.css
#000000に変更
再ロードして反映

他に同様に薄いところがないかチェックしてみます。

フッター住所などが黒くなってしまいました。

あの値がここにも影響を受けていたので、フッターのCSSを白に調整していきます。方法をchatGPTに聞いてみましょう。

<p>東京都千代田区東神田1-7-10</p> が白色の文字になるようにして、下記の影響を受けないで p { color: #000000; font-size: 16px; font-weight: 300; line-height: 2; margin: 0; }

chatGPTへの引数

この要件を満たすには、特定の<p>タグに対してインラインスタイルを適用するか、CSSのクラスを使ってスタイルを適用する必要があります。以下に2つの方法を示します。

インラインスタイルを使用する方法

HTMLの<p>タグに直接スタイルを適用します。これは、他のスタイル定義の影響を受けずに特定の要素にスタイルを適用する最も簡単な方法です。

chatGPT回答
<p style="color: white;">東京都千代田区東神田1-7-10</p>

CSSクラスを使用する方法
CSSで新しいクラスを作成し、そのクラスを特定の<p>タグに適用します。この方法は、同じスタイルを複数の要素に適用する場合に便利です。

続chatGPT回答
.white-text {
  color: white !important;
}

今回は「インラインスタイル」を適用します。複数箇所ありますので、置換することにします。

インラインスタイルへの置換変更時
エラー発生

JSXだと{{}}で囲んでくれよとのことですので、やはり「CSSクラスを使用する方法」にシフトしましょう。

CSSクラス使用にシフト
.white-textを追加
白くなりました

これで全要素を網羅したでしょうか?ただ順番が適切ではないので、今一度マーケティング視点でどの順番が良いのか調整していきます。

トップページに実績を掲載していくことが最重要ですので、問い合わせの前にそれを持っていきます。また、何を解決したいのかなどの理念や事業概要を説明した後に、実績が来るようにすると効果的ですので、さらにそれを前に持っていくようにします。

1


2


3


4


5


6

あとは、理念のショート動画を撮影してから差し替え、実績を更新していけば、マーケティング視点を抑えたホームページの土台は完成です。そして、タブ表示時の文言修正とGoogleアナリティクス対応ができていないのと、その修正を行っていきます。ちなみに、KPIはブックマーク登録者数です。

タブbefore

例によって、grepします。

grep -lr "Preview" ./src 

./src/app/page.js

code ./src/app/page.js
titleを発見

7.faviconの調整方法


 favicon.icoが使用されていますが、現時点では反映されていないので、パスが読み込めていない可能性があります。一旦chatGPTに聞いてみましょう。

export const metadata = { title: "ブルテナサス - 基幹システム開発DAO", icons: { icon: "/favicon.ico", shortcut: "/favicon.ico", other: generateStylesheetObject([ "https://fonts.googleapis.com/css?family=Poppins:100,200,300,400,500,600,700,800,900&display=swap", "https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght@100;200;300;400;500;600;700;800;900&display=swap", "https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800&display=swap", "/css/light.css", ]), }, }; favicon.icoファイルがpublic/img/の下にあるんだけれど、読み込まれていないのはどうして?

chatGPTへの引数

favicon.ico ファイルが読み込まれていない理由は、その参照パスが間違っている可能性があります。metadata オブジェクト内で favicon.ico のパスはルートディレクトリ(/)に設定されていますが、ファイルは public/img/ ディレクトリに存在するとのことです。

この問題を解決するには、favicon.ico への参照パスを修正する必要があります。以下のように metadata オブジェクトを更新してみてください:

chatGPT回答1
export const metadata = {
  title: "ブルテナサス - 基幹システム開発DAO",
  icons: {
    icon: "/img/favicon.ico",
    shortcut: "/img/favicon.ico",
    other: generateStylesheetObject([
      "https://fonts.googleapis.com/css?family=Poppins:100,200,300,400,500,600,700,800,900&display=swap",
      "https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght@100;200;300;400;500;600;700;800;900&display=swap",
      "https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800&display=swap",
      "/css/light.css",
    ]),
  },
};

この変更により、favicon.ico へのパスが public/img/ ディレクトリに正しく指定されるため、ブラウザがアイコンファイルを正しく読み込むはずです。また、ウェブサイトの設定やサーバーの構成によっては、ブラウザのキャッシュをクリアするか、サーバーを再起動する必要があるかもしれません。

chatGPT回答2

要するに「"/img"を入れてみて」ということですので、入れてみます。

反映された

シンプルにテンプレートがディレクトリを間違っていたようです。でも、このfaviconでは意味を成さないので、せめて「B」にしたいので、chatGPTにお願いしてみました。

絶妙にダサいです。。

なので、今度は下記のサイトを利用することにします。

テキストと色を設定

簡単にfaviconが生成できました。

タブafter

ロゴと本当は同一性を打ち出した方がマーケティング視点では良いのかもしれませんが、無料領域で極力走り抜け、サービスが立ち上がってきた時に、プロの力でリブランディングしても良いという方向性で今回は進行します。

8.Googleアナリティクスの実装方法

 次はGoogleアナリティクスです。page.jsと他のサイトでうまくアナリティクスが動いているコードを合体させます。

useEffect(() => { // Initialize gtag.js window.dataLayer = window.dataLayer || []; function gtag() { window.dataLayer.push(arguments); } gtag("js", new Date()); gtag("config", ""); }, []); 上と下を組み合わせて import Script from "next/script"; //= Scripts import generateStylesheetObject from "@/common/generateStylesheetsObject"; //= Common Components import LoadingScreen from "@/components/Common/Loader"; import Cursor from "@/components/Common/Cursor"; import ProgressScroll from "@/components/Common/ProgressScroll"; //= Page Components import CircleBg from "@/components/Demos/CircleBg"; // import Header from "@/components/Demos/Header"; import MainContent2 from "@/components/Demos/MainContent2"; export const metadata = { title: "ブルテナサス - 基幹システム開発DAO", icons: { icon: "/img/favicon.ico", shortcut: "/img/favicon.ico", other: generateStylesheetObject([ "https://fonts.googleapis.com/css?family=Poppins:100,200,300,400,500,600,700,800,900&display=swap", "https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght@100;200;300;400;500;600;700;800;900&display=swap", "https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800&display=swap", "/css/light.css", ]), }, }; export default function LandingPreview() { return ( <> <LoadingScreen /> <Cursor /> <ProgressScroll /> <CircleBg /> {/* <Header /> */} {/* <MainContent /> */} <MainContent2 /> <Script strategy="beforeInteractive" src="/js/wow.min.js"></Script> <Script strategy="beforeInteractive" src="/js/splitting.min.js"></Script> <Script strategy="beforeInteractive" src="/js/simpleParallax.min.js" ></Script> <Script strategy="beforeInteractive" src="/js/isotope.pkgd.min.js" ></Script> <Script strategy="lazyOnload" src="/js/pace.min.js"></Script> <Script strategy="lazyOnload" src="/js/wowInit.js"></Script> </> ); }

chatGPT引数

To integrate the Google Analytics setup (using useEffect) with your existing Next.js component, you can include the useEffect hook within your LandingPreview component. Additionally, to comply with Next.js practices, you should use the Script component from next/script to load external scripts instead of directly manipulating the DOM. Here's how you can combine the Google Analytics setup with your existing component:

chatGPT回答1
import { useEffect } from 'react';
import Script from 'next/script';

//= Common Components
import LoadingScreen from '@/components/Common/Loader';
import Cursor from '@/components/Common/Cursor';
import ProgressScroll from '@/components/Common/ProgressScroll';
//= Page Components
import CircleBg from '@/components/Demos/CircleBg';
// import Header from '@/components/Demos/Header';
import MainContent2 from '@/components/Demos/MainContent2';

export const metadata = {
  // ... your metadata
};

export default function LandingPreview() {
  useEffect(() => {
    // Initialize gtag.js
    window.dataLayer = window.dataLayer || [];
    function gtag() {
      window.dataLayer.push(arguments);
    }
    gtag('js', new Date());
    gtag('config', 'YOUR_GA_TRACKING_ID'); // Replace with your Google Analytics Tracking ID
  }, []);

  return (
    <>
      <LoadingScreen />
      <Cursor />
      <ProgressScroll />

      <CircleBg />
      {/* <Header /> */}
      {/* <MainContent /> */}
      <MainContent2 />

      <Script strategy="beforeInteractive" src="/js/wow.min.js"></Script>
      <Script strategy="beforeInteractive" src="/js/splitting.min.js"></Script>
      <Script strategy="beforeInteractive" src="/js/simpleParallax.min.js"></Script>
      <Script strategy="beforeInteractive" src="/js/isotope.pkgd.min.js"></Script>
      <Script strategy="lazyOnload" src="/js/pace.min.js"></Script>
      <Script strategy="lazyOnload" src="/js/wowInit.js"></Script>
      {/* Add additional external scripts here if needed */}
    </>
  );
}

In this code:useEffect is imported from react and used to initialize Google Analytics.
Make sure to replace 'YOUR_GA_TRACKING_ID' with your actual Google Analytics Tracking ID.
The Script component from next/script is used for loading external JavaScript files.
Other components and scripts remain as they are in your original code.

chatGPT回答2

英語になってしまいましたが、そのまま適用してみます。

Googleアナリティクスコード追加
エラー発生

このエラーメッセージ自体をchatGPTに投げてみます。

The error you're encountering is due to the usage of useEffect in a server component in Next.js. The useEffect hook is part of React's client-side capabilities and can't be used in server components. In Next.js, files in the pages directory are treated as server components by default, and they render on the server.

To fix this issue, you'll need to create a client component that uses useEffect and then import that component into your page. Here's how you can do it:Create a Client Component for Google Analytics: Create a new file, let's say GoogleAnalytics.js, in your components directory. This file will be a client component.

chatGPT回答1
// src/components/GoogleAnalytics.js
import { useEffect } from 'react';

const GoogleAnalytics = () => {
  useEffect(() => {
    // Initialize gtag.js
    window.dataLayer = window.dataLayer || [];
    function gtag() {
      window.dataLayer.push(arguments);
    }
    gtag('js', new Date());
    gtag('config', 'YOUR_GA_TRACKING_ID'); // Replace with your Google Analytics Tracking ID
  }, []);

  return null; // This component doesn't render anything
};

export default GoogleAnalytics;

mport the Client Component in Your Page: Modify your page component to import the GoogleAnalytics component. Use the use client directive to indicate that this is a client-side component.

chatGPT回答2
// ./src/app/page.js
import GoogleAnalytics from '@/components/GoogleAnalytics'; // Adjust the path as necessary

export default function LandingPreview() {
  return (
    <>
      <GoogleAnalytics />
      {/* Rest of your components */}
    </>
  );
}

In this setup, GoogleAnalytics is a client component that uses the useEffect hook to initialize Google Analytics. By importing this component into your page component, you keep the server-side and client-side logic separate, which aligns with Next.js's architecture for server and client components.

Remember to replace 'YOUR_GA_TRACKING_ID' with your actual Google Analytics Tracking ID. Also, make sure the import paths match the structure of your project.

chatGPT回答3

'use client';を使用してほしいそうなので、そのように修正していきます。YOUR_GA_TRACKING_IDはあなたのGタグに合わせて変更してください。

GoogleAnalytics対応
import GoogleAnalytics

本件はnextjsのアーキテクチャ特有の事象であり、サーバーサイドとクライアントサイドで分けて処理されていることが起因していました。クライアントサイドで処理されることによって、エラーが発生しなくなります。ちなみに、「Gタグって何?」という方は下記から取得してみてください。

9.ブックマークをKPIにする方法

 これでKPIもバッチリ取れるようになるのですが、ブックマークってどこで参照できるのか、またchatGPTに聞いてみましょう。

ブックマークをKPIにしたいんだけれど、アナリティクスのどこで参照できるの?

chatGPT引数

Google Analyticsを使用してウェブサイトのブックマーク(ユーザーがサイトをお気に入りに追加する行動)を直接トラッキングすることはできません。これは、ブックマークはブラウザの内部操作であり、ウェブページやサーバーから直接アクセスやトラッキングができないからです。

しかし、ブックマークを間接的に測定する方法がいくつかあります。これらの方法は完全ではありませんが、ユーザーがサイトに戻ってくる傾向を測定するのに役立ちます。例えば:リピートビジターの分析: Google Analyticsでリピートビジター(再訪問者)のデータを見ることで、ユーザーがサイトに興味を持っているかどうかの指標を得ることができます。リピートビジターの割合が高い場合、ユーザーがサイトをブックマークしている可能性が高いです。
ダイレクトトラフィックの監視: ユーザーがブックマークや手入力でサイトにアクセスすると、これは「ダイレクトトラフィック」としてGoogle Analyticsに記録されます。ダイレクトトラフィックの増加は、ユーザーがサイトのURLを記憶しているか、ブックマークしていることを示唆している可能性があります。
カスタムイベントの使用: ユーザーが特定のアクション(例えば「お気に入りに追加」ボタンのクリック)をするときにカスタムイベントを発火させ、これをGoogle Analyticsでトラッキングすることもできます。ただし、これはブックマークそのものではなく、あくまでサイト内でのユーザーの行動を測定するものです。
セッションの継続時間とエンゲージメント: ブックマークされたサイトは、ユーザーが関心を持っていることが多いので、これらのサイトのセッション時間やエンゲージメントが高い傾向にあります。これらの指標を分析することで、ユーザーの関心度を間接的に測定することができます。


これらの方法は完璧ではないものの、ブックマークに関連するユーザー行動の傾向を把握するのに役立つでしょう。

chatGPT回答

ブックマークはKPIにできない。。りゅう先生どういうことでしょうか?と突っ込みたいところですが、検索して調べてみると答えっぽいのを発見しました。

ブックマークからのアクセス

ノーリファラーとなるケースで特に多いのが、ユーザーがブラウザに保存しているブックマークからのアクセスです。各チャネルからの流入を正確に捕捉できている場合は、「ノーリファラー≒ブックマークからの流入」とみなして差し支えないでしょう。

https://wacul-ai.com/blog/access-analysis/google-analytics-method/google-analytics-channel/


赤枠内にNo Referrerが増えると良いとのこと

ということで、「タブ表示時の文言修正とGoogleアナリティクス」対応が完了しました。あと忘れていけないのは、メタデータと言語変更です。Googleに適切にクローリングして頂かないと、検索されませんので、ここは力を入れて修正していきます。

layout.jsのbefore
layout.jsのafter

10.テストテストテスト

 大体できてきたので、ユーザー目線でテストしながら文言の見直しと簡易修正を行なっていきます。

ニュースはまだないので、サンプルで1つだけにし、リンクをhref="#0"にする
ラジオボタンが整っていないので整理が必要


スペースがあるので沿革情報を入れる

下記3点を修正していきます。

  1. ニュースはまだないので、サンプルで1つだけにし、リンクをhref="#0"にする

  2. モバイル画面においてラジオボタンが整っていないので整理が必要

  3. フッターにスペースがあるので沿革情報を入れる

PRページができるまでは、href="#0"で制御

1は速攻で、次は2です。chatGPTとBardに聞いてみたところ、Bardが良い回答をしてくれました。ちなみに、日本語の質問を最後に持ってくることによって、回答を日本語でしてくれます。

import React, { useState } from "react"; //= Components import Split from "@/components/Common/Split"; //= Static Data import contentFormData from "@/data/contact-form.json"; function ContactForm({ theme }) { const [inquiryType, setInquiryType] = useState("general"); return ( <section className="contact section-padding"> <div className="container"> <div className="row"> <div className="col-lg-6"> <div className="form md-mb50"> <h4 className="fw-700 color-font mb-50">お問い合わせフォーム</h4> <form id="contact-form" method="post" action="https://bletainasus.form.newt.so/v1/WDSy5p8uL" > <div className="messages"></div> <div className="controls"> <div className="form-group"> <div className="radio-buttons"> <label> <input type="radio" value="general" checked={inquiryType === "general"} onChange={() => setInquiryType("general")} /> 一般的なお問い合わせ </label> <label> <input type="radio" value="interview" checked={inquiryType === "interview"} onChange={() => setInquiryType("interview")} /> 取材 </label> <label> <input type="radio" value="jv" checked={inquiryType === "jv"} onChange={() => setInquiryType("jv")} /> ビジネスアライアンス(協業) </label> </div> </div> <div className="form-group"> <input id="form_name" type="text" name="name" placeholder="お名前" required="required" /> </div> <div className="form-group"> <input id="form_email" type="email" name="email" placeholder="メールアドレス" required="required" /> </div> <div className="form-group"> <textarea id="form_message" name="message" placeholder="メッセージ" rows="4" required="required" ></textarea> </div> <button type="submit" className={`butn ${theme === "light" ? "dark" : "bord"}`} > <span>送信</span> </button> </div> </form> </div> </div> <div className="col-lg-5 offset-lg-1"> <div className="cont-info"> <h4 className="fw-700 color-font mb-50">連絡先</h4> <Split> <h3 className="wow" data-splitting> {contentFormData.title} </h3> </Split> <div className="item mb-40"> <h5> <a href="#0">{contentFormData.email}</a> </h5> <h5>{contentFormData.phone}</h5> </div> {/* <Split> <h3 className="wow" data-splitting> Visit Us. </h3> </Split> <div className="item"> <h6> {contentFormData.location.first} <br /> {contentFormData.location.second} </h6> </div> */} <div className="social mt-50"> <a href="#0" className="icon"> <i className="fab fa-facebook-f"></i> </a> {/* <a href="#0" className="icon"> <i className="fab fa-twitter"></i> </a> */} <a href="#0" className="icon"> <i className="fab fa-pinterest"></i> </a> {/* <a href="#0" className="icon"> <i className="fab fa-behance"></i> </a> */} </div> </div> </div> </div> </div> </section> ); } export default ContactForm; モバイル画面でラジオボタンがぐちゃぐちゃなんだけど、ちゃんと整えられる?

Bard引数

はい、コードを拝見して、モバイル画面でラジオボタンが整うように調整できます。いくつかの改善策を提案します。

1. レイアウト調整:Flexboxの活用: ラジオボタンを囲む radio-buttons divに display: flex と flex-direction: column を適用して、縦並びにします。
メディアクエリの追加: モバイル画面のみにCSSを適用するには、メディアクエリを使用します:

2. 余白の調整:label 要素に margin-bottom を追加して、ラジオボタンの間の縦の空白を広げます。


3. フォントサイズの調整:モバイル画面では、ラベルのフォントサイズが大きすぎる可能性があります。 @media (max-width: 768px) 内で、ラベルのフォントサイズを小さくします。


4. ラベルの改行:ラベルのテキストが長すぎる場合、 word-wrap: break-word を適用して、改行させるようにします。


5. タッチターゲットの拡張:タッチデバイスでの操作性を高めるには、ラジオボタン自体のサイズを少し大きくするか、透明な背景色を label 要素に追加してタッチターゲットを拡張します。

Bard回答
.radio-buttons {
  /* デフォルトのレイアウト */
}

@media (max-width: 768px) {
  .radio-buttons {
    display: flex;
    flex-direction: column;
  }

  .radio-buttons label {
    margin-bottom: 10px; /* ラジオボタンの間の余白 */
    font-size: 14px; /* ラベルのフォントサイズ調整 */
    word-wrap: break-word; /* ラベルの改行 */
  }

  .radio-buttons input[type="radio"] {
    width: 20px; /* ラジオボタンのサイズ調整(例) */
  }
}
light.cssに反映
整列ができ、採用のためのボタンも追加

続いて、フッターにスペースがあるので沿革情報を入れます。

フッターのコメントアウトを解除
Recent Newsを沿革に調整

沿革に写真やメルマガ用のEmailはいらないのでコメントアウトし、後は日本語化していきます。

沿革が増えたら、引越す前提で掲載

ということで、「メディア実績と協業」の2つを目的としたホームページができましたので、いよいよインターネット空間に解き放ちます。

11.インターネット空間へのデプロイ方法

 まずその準備として、手元でビルドを行います。

yarn build
yarn run v1.22.17
warning ../../../package.json: No license field
$ next build
   Disabled SWC as replacement for Babel because of custom Babel configuration ".babelrc" https://nextjs.org/docs/messages/swc-disabled
   Using external babel configuration from /Users/takayamasashi/Desktop/vie/vie_nextjs_13/.babelrc
 ⚠ It looks like there is a custom Babel configuration can be removed .
Failed to compile.

./src/components/Contact/ContactForm.jsx
ReactServerComponentsError:

You're importing a component that needs useState. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.
Learn more: https://nextjs.org/docs/getting-started/react-essentials

   ╭─[/Users/takayamasashi/Desktop/vie/vie_nextjs_13/src/components/Contact/ContactForm.jsx:1:1]
 1import React, { useState } from "react"; //= Components
   ·                 ────────
 23import Split from "@/components/Common/Split"; //= Static Data
   ╰────

Maybe one of these should be marked as a client entry with "use client":
  ./src/components/Contact/ContactForm.jsx
  ./src/app/(dark)/contact/contact-dark/page.js


> Build failed because of webpack errors
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
ContactForm.jsxにも"use client";が必要そう
yarn build
yarn run v1.22.17
warning ../../../package.json: No license field
$ next build
   Disabled SWC as replacement for Babel because of custom Babel configuration ".babelrc" https://nextjs.org/docs/messages/swc-disabled
   Using external babel configuration from /Users/takayamasashi/Desktop/vie/vie_nextjs_13/.babelrc
 ⚠ It looks like there is a custom Babel configuration can be removed .
 ✓ Creating an optimized production build    
 ✓ Compiled successfully
   Linting and checking validity of types  .. ⨯ ESLint: Failed to load config "next/babel" to extend from. Referenced from: /Users/takayamasashi/Desktop/vie/vie_nextjs_13/.eslintrc.json
 ✓ Linting and checking validity of types    
 ✓ Collecting page data    
 ✓ Generating static pages (56/56) 
 ✓ Finalizing page optimization    

Route (app)                                   Size     First Load JS
┌ ○ /                                         6.01 kB         105 kB
├ ○ /_not-found                               883 B          88.3 kB
├ ○ /about/about-dark                         151 B           130 kB
├ ○ /about/about-light                        150 B           130 kB
├ ○ /blog-details/blog-details-dark           905 B          96.7 kB
├ ○ /blog-details/blog-details-light          905 B          96.7 kB
├ ○ /blog-grid/blog-grid-dark                 905 B          96.7 kB
├ ○ /blog-grid/blog-grid-light                905 B          96.7 kB
├ ○ /blog-list/blog-list-dark                 905 B          96.7 kB
├ ○ /blog-list/blog-list-light                905 B          96.7 kB
├ ○ /blog/blog-dark                           905 B          96.7 kB
├ ○ /blog/blog-light                          905 B          96.7 kB
├ ○ /contact/contact-dark                     142 B            98 kB
├ ○ /contact/contact-light                    142 B            98 kB
├ ○ /homepage/home1-dark                      154 B           135 kB
├ ○ /homepage/home1-light                     155 B           135 kB
├ ○ /homepage/home2-dark                      2.54 kB         129 kB
├ ○ /homepage/home2-light                     2.54 kB         129 kB
├ ○ /homepage/home3-dark                      151 B           134 kB
├ ○ /homepage/home3-light                     150 B           134 kB
├ ○ /homepage/home4-dark                      2.56 kB         132 kB
├ ○ /homepage/home4-light                     2.56 kB         132 kB
├ ○ /homepage/home5-dark                      155 B           132 kB
├ ○ /homepage/home5-light                     154 B           132 kB
├ ○ /homepage/home6-dark                      151 B           134 kB
├ ○ /homepage/home6-light                     151 B           134 kB
├ ○ /homepage/home7-dark                      154 B           139 kB
├ ○ /homepage/home7-light                     155 B           139 kB
├ ○ /homepage/home8-dark                      151 B           137 kB
├ ○ /homepage/home8-light                     151 B           137 kB
├ ○ /mobile-app/mobile-app-dark               142 B           129 kB
├ ○ /mobile-app/mobile-app-light              142 B           129 kB
├ ○ /mobile-app/portfolio-dark                142 B          98.2 kB
├ ○ /mobile-app/portfolio-light               142 B          98.2 kB
├ ○ /mobile-app/pricing-plan-dark             142 B          98.3 kB
├ ○ /mobile-app/pricing-plan-light            142 B          98.3 kB
├ ○ /mobile-app/services-dark                 141 B          98.3 kB
├ ○ /mobile-app/services-light                142 B          98.3 kB
├ ○ /mobile-app/shop-dark                     142 B          98.1 kB
├ ○ /mobile-app/shop-light                    142 B          98.1 kB
├ ○ /project-details2/project-details2-dark   1.68 kB        97.5 kB
├ ○ /project-details2/project-details2-light  1.68 kB        97.5 kB
├ ○ /showcase/showcase-dark                   1.37 kB         128 kB
├ ○ /showcase/showcase-light                  1.37 kB         128 kB
├ ○ /showcase2/showcase2-dark                 1.58 kB         128 kB
├ ○ /showcase2/showcase2-light                1.58 kB         128 kB
├ ○ /showcase3/showcase3-dark                 1.67 kB         129 kB
├ ○ /showcase3/showcase3-light                1.67 kB         129 kB
├ ○ /works/works-dark                         1.84 kB        97.6 kB
├ ○ /works/works-light                        1.84 kB        97.6 kB
├ ○ /works2/works2-dark                       142 B          98.1 kB
├ ○ /works2/works2-light                      142 B          98.1 kB
├ ○ /works3/works3-dark                       141 B          98.1 kB
└ ○ /works3/works3-light                      142 B          98.1 kB
+ First Load JS shared by all                 87.4 kB
  ├ chunks/2503-74392824140ec6c8.js           34.4 kB
  ├ chunks/fd9d1056-8ea860660145e754.js       50.9 kB
  ├ chunks/main-app-37bdeff11a8b0c49.js       234 B
  └ chunks/webpack-f0c5cd87759e5799.js        1.85 kB


○  (Static)  automatically rendered as static HTML (uses no initial props)

✨  Done in 14.52s.

成功しました。では、githubに入って、リポジトリを作成し、このソースをプッシュしていきましょう。

新規作成

ちなみにビルドすると、サイズの大きい.nextフォルダがその時に作成されてしまいますので、.gitigonreファイルを作成し、.next/とnode_modules/をプッシュ条件から避けるように設定しておきます。viコマンドの使用方法が不明な方は以下を参考にしてみてください。

vi .gitignore

.next/
node_modules/

:wq
echo "# bletainasus" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:takayanomasashi2/bletainasus.git
git push -u origin main
コミット完了

vercelのサービスを利用して、デプロイしていきます。

NEXT_PUBLIC_NEWT_FORM_ENDPOINTの環境変数設定が必要

下記のテストURLで既に参照できるようになりましたが、ドメインを与えていきます。

https://bletainasus-zhxt-3ldgu3xno-takayanomasashi2.vercel.app/

awsのroute53で取得したドメインを割当

12.メタデータの修正方法

 この時点では下記のように写真がなかったり、「ブルテナサス - 基幹システム開発DAO」と説明が繰り返してしまっているので、メタデータの修正を行っていきます。

リリース直後のメタデータ情報
ここが問題
調整完了
git add . ; git commit -m "fix meta" ; git push

このコマンドでgitの更新をかけます。vercelはgitの更新を自動で検知し、再度vercel環境でbuildしてくれます。

build中

buildした後もキャッシュクリアされないと反映されないので、今度はslackにURLを貼付して確認しました。

大丈夫そうです

ちなみに、ロゴは躍動感があり、色が鮮やな方が好印象という、早稲田大学の研究で発表されているそうです。躍動感とは、牛乳をコップに注いでいる写真のような動きのことです。デフォルトでこのロゴは両方を満たしている形なので、マーケティング的にも悪くはないのかもしれません。

13.実機でもテストテストテスト

 ということで、PC上でできることはほぼ完結しましたので、次はスマホでの確認をしていきます。できれば、iPhoneとandroidの両方で確認した方がベターです。

iPhone

ラジオボタンが上記のようにやはり少しずれていたり、横へのスライドが動いたりするので、これを固定するように修正します。

横スライド発生例

chatGPT4.0では課金2,000円/月が必要ですが、写真添付も可能になりましたので、上記の写真を添付した上で下記のメッセージをプロンプトに投げます。

ラジオボタンが写真のように、少しずれてしまう問題を解決して。下記のcssを修正して @media (max-width: 768px) { .radio-buttons { display: flex; flex-direction: column; } .radio-buttons label { margin-bottom: 10px; /* ラジオボタンの間の余白 */ font-size: 14px; /* ラベルのフォントサイズ調整 */ word-wrap: break-word; /* ラベルの改行 */ } .radio-buttons input[type="radio"] { width: 20px; /* ラジオボタンのサイズ調整(例) */ } }

chatGPT引数

このスクリーンショットには、ラジオボタンが少しズレて表示されている問題がありますね。CSSを調整して、この問題を修正するためのいくつかの提案をします。

まず、ラジオボタンのズレを直すためには、vertical-align プロパティを使用すると良いでしょう。これにより、ラジオボタンとラベルのテキストが垂直方向に揃います。

また、ラジオボタン自体の位置を調整するために margin または padding を適切に設定することで、デザインの整合性を取ることが可能です。

以下に、修正したCSSの例を示します。このコードでは、vertical-align プロパティを使ってラジオボタンとテキストの位置を中央揃えにし、margin で適切な余白を設定しています。

chatGPT回答
@media (max-width: 768px) {
  .radio-buttons {
    display: flex;
    flex-direction: column;
  }

  .radio-buttons label {
    margin-bottom: 10px; /* ラジオボタンの間の余白 */
    font-size: 14px; /* ラベルのフォントサイズ調整 */
    word-wrap: break-word; /* ラベルの改行 */
    vertical-align: middle; /* ラベルを中央揃えにする */
  }

  .radio-buttons input[type="radio"] {
    width: 20px; /* ラジオボタンのサイズ調整 */
    height: 20px; /* ラジオボタンの高さを調整 */
    vertical-align: middle; /* ラジオボタンを中央揃えにする */
    margin-right: 5px; /* ラベルのテキストとの間に余白を作る */
  }
}

この修正でラジオボタンのズレは修正されました。

css適用時
css適用後

androidでは横へのスライドは発生しないのですが、"overflow-x: hidden;"のCSSを足してもiPhoneでは発生してしまいます。調査した結果、下記に答えが載っていました。

html {
    overflow-x : hidden;
    -webkit-overflow-scrolling: touch;
}

body {
    overflow-x : hidden;
    -webkit-overflow-scrolling: touch;
}
iPhone横ブレ補正用css追加

さいごに

 以上「オンラインプレゼンス」の高いホームページの作成方法となります。あとは、代表挨拶とDAO理念を紹介する動画を更新するなどして、PR TIMESなどに投資し、SNSと繋ぎながら、ブックマーク登録(ノーリファラル)をKPIとして、このサイトを成長させていけば、事業も同時に成長していくという流れです。

こんなにたくさんやるのは面倒くさい?

そんな方は、今まさに開発した下記のお問い合わせフォームにメッセージをいただけましたら、御見積及び代行業務させていただきますので、どうぞよろしくお願いいたします。

最後まで読んでいただき誠にありがとうございました。

この記事が気に入ったらサポートをしてみませんか?