【開発日記】初心者がOpenAI API×React×Next.jsでアプリを作ってみた


:::note info
完成したアプリ(2023/02/01記)
:::
https://episode-title-generator.vercel.app/


## はじめに

初心者が勉強を兼ねて、javascriptとopenaiのapiを使ってアプリを作りました。
その試行錯誤の跡です。
22日分あります。ちょくちょくさぼってます。

## アプリ要件
- フロントエンド
    - Reactjs
    - Nextjs
    - Chakra UI
- バックエンド
    - Node.js
- DB
    - PlanetScale
- ORM
    - Prisma
- API
    - OpenAI

## 1日目

やったこと
- node.jsのインストール等環境構築
- javascriptのexampleを使ってみた
- **漫画のタイトルを生成するWebアプリ**を作ることを決めた

作るアプリを決めた時の記事

https://qiita.com/kajiyai/items/b8c9b9fec255dedda38f

https://beta.openai.com/examples/default-js-helper

## 2日目

1日目で行った表示をWebブラウザ上で表示しようと試みた。
Node.js,Next.js,React,javascript,typescriptの全てが分からず何とかならなかった。
そのため、こちらの動画を見始めた(なぜかNext.jsから見始めてしまった...)

https://www.youtube.com/playlist?list=PLX8Rsrpnn3IUGEyanrHYGjY1WOzNe7Jd-

https://www.youtube.com/playlist?list=PLX8Rsrpnn3IWPoM7-1YPDksRRkamRY25k


## 3日目

動画を見る中でアロー関数に躓きつつ、動画を見終えた(ハンズオンで手も動かした)。


    .then(res => res.json())
が

    .then((res) => {
      return res.json()
    })
の省略であることを理解した。



**アロー関数**
- 関数を省略して書くための構文
- パラメータresの()を省略可能
- 1行だとreturnも省略可能

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions



## 4日目

公式の配布しているスターターキットを見つけ、簡単に組み立てた
タイトル生成出来てる感.....!

https://github.com/openai/openai-quickstart-node/blob/master/pages/api/generate.js

![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/e2719dcd-ece2-bce8-eb67-90033a7a2f6f.gif)



## 5日目

Twitterにシェアするボタンを作った

やったこと
- OGPの設定
    - こちらはデプロイしてurlが確定しないとチェックできない模様
    - metaタグは設定したが、うまく動いてるかどうかは不明。
- シェアボタンの設定
    - こちらは動作確認できた。
- プロンプト・プレースホルダ
    - **キーワードを含む**タイトル生成の仕様にした

**シェアボタンを押すと生成されるHTML**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/a3d27ab5-ae5f-be02-69e2-a3323c5c6db6.png)

**日本語で出力されるようにプロンプトを変更**
![ezgif.com-gif-maker (2) (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/d4b4ddce-9047-0ca9-8195-0a16d0b59cb4.gif)


OGP:Open Graph Protcolの略。各種SNSにシェアする時の投稿画面をカスタマイズすることが出来る。詳しくはこちら

https://kaikoku.blam.co.jp/client/digimaguild/knowledge/sns-pr/498

## 6日目~10日目

一生漫画読んでた

## 11日目

Chakra UIとNext.jsのチュートリアルを参考に色やら大きさやらを変えてみた

【テキスト入力前】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/de42de8e-8d9e-a138-d811-1403780ce931.png)

【”海賊”と入力後】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/69c66273-1f96-bb37-92d6-f69288fb5d0b.png)


https://chakra-ui.com/getting-started/nextjs-guide


## 12日目

Chakra UIのcardを使ってみた。出力結果をカードで出力するようにしてみた。


![localhost_3000_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/af7ea4d7-17a2-44e7-5992-352d37e97e26.png)


その際、APIの出力結果を整える必要があり、沼った。
少し整えて表示するだけのはずが同じところをぐるぐると。。

## 13日目

やったこと
- 12日目のエラー修正
    - カードごとに値の出し分け成功
- 画像生成APIとのやり取り


12日のエラーは変数や関数の**スコープ**について理解をしていなかったからだった。
ifブロックの中でconst宣言、ブロック外で呼び出しをしており、undefinedだった。
ついでに変数定義の種類(const,let,var)も知らなかったので、ざっくり知った。

https://qiita.com/tomcky/items/988fc5f56d019e9dc097


テキストの時は成功していたが、画像生成ではAPIの出力結果をfetch出来ないエラーが発生した。
→JSONの存在しないキーを参照していた。中身を確認しよう


生成した画像はurlが返されるので、next.js上で表示できるように工夫する


https://chaika.hatenablog.com/entry/2021/07/20/083000


## 14日目

やったこと
- 画像生成APIとのやり取り成功
    - ただ、画像生成するとすべてのカードの画像が変更されてしまっている。

画像はキーワードに"新"と入力した結果。
真ん中のカード「新幹線でのミステリー」で画像生成ボタンを押したら生成された画像。

![manga-title-generator-mu.vercel.app_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/b072f896-85cc-2ed8-4288-0ce5242322f2.png)


## 15日目

やったこと
- 結果を表示するカード毎の画像出し分け


キーワード"コイル"と入力し、2つ目のカードの画像生成ボタンを押下した結果

![localhost_3000_ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/6640e1da-3ca8-cee7-ab81-1af56f7ec897.png)


## 16日目
やったこと
- デザインをchakra ui templateを少しいじって変更
    - レスポンシブ設定もした
- 画像生成用プロンプトを生成するapiの設定
    - プロンプト生成ボタンを作った


もっと直観的に操作できるようにしたい。

現在はプロンプトボタン→画像生成ボタンの流れを踏まないとエラーになる
本来ならば`画像生成ボタン→(裏でプロンプト生成APIを通してプロンプト作成)→画像表示`が理想。
react,react hooks,非同期処理,らへんをまた復習


![manga-title-generator-sable.vercel.app_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/7ce15b91-caab-7c22-2fe0-c666191aaf73.png)


こちらの、midjurneyのプロンプト生成を参考にプロンプトを生成してもらう

https://github.com/f/awesome-chatgpt-prompts


## 17日目

寝てた

## 18日目

やったこと
- モードのトグルボタンをつくった
    - ダークモードに出来るようになった
    - 記事書いた
- カルーセルまたはテスティモニーで利用例的なのを作ろうとした
    - カルーセルでスライドで見せるのがよさそう
        - エラーエラーエラー
    - 最悪テスティモニーで表示する。

書いた記事

https://qiita.com/kajiyai/items/5000b46654e98a3217fd


## 19日目

やったこと
- 使用例作った
    - テスティモニーで表示することに
    - アコーディオンで表示した
- 文言変更・コピーボタン作成など
    - 作品のタイトルでなく、エピソード毎のタイトルを支援することにした

## 20日目
やったこと
- DB作る
    - Plantscale,prismaの初期設定

参考

https://zenn.dev/nbr41to/articles/adabca83b2e6ea

## 21日目
やったこと
- DB作る
    - 日付で条件指定して使用制限


1日のAPI使用上限を100回に指定した。
APIを呼び出すタイミングでDB接続し、現在時刻までに使用されたレコードの数を数えて、100回を超えたらAPIを呼び出せないように設定した。


参考
prismaのwhereに複数条件の指定がとても参考になった

https://wp-kyoto.net/prisma-nested-where-query/

https://tech.smartcamp.co.jp/entry/try-prisma-to-product-filter


時間の文字列⇔Date型変換について

https://www.delftstack.com/ja/howto/javascript/convert-string-to-date-in-javascript/

文字列の中に余計なスペースがあるとNG,タイムゾーンはUTC(.000Z)

公式pranetScaleのvercelデプロイドキュメント


https://planetscale.com/docs/tutorials/deploy-to-vercel



## 22日目
やったこと
- Twitterのogp設定
    - 画像の表示
- アプリ完成

相対パスでは表示されない模様。

https://zenn.dev/nbr41to/articles/a84f09a6a9ac65


こちらのチェックツールでチェックした

https://web-toolbox.dev/tools/ogp-checker


一旦完成した

https://episode-title-generator.vercel.app/



やりたかった奴ら
- Typescriptで書く
- OGPの動的な画像生成
- ロード中の表示切替
    - スケルトンとかスピナーとか
- カルーセル
    - 使用例にカルーセル

精進

## Tips

gifを作成するときに参照

https://qiita.com/Bu-Kohei/items/c84dee5cef71d6cb1bd8


なぜか画像のパスを以下のように設定したら通った
src=**public**/img/idea.jpgとしたら通らない。

フォルダ構成
- pages
    - index.jsx
- public
    - img
        - idea.jpg

下のコードをindex.jsxに記載

    <Image src="/img/idea.jpg" width={500} height={500} objectFit="contain" vclassName={styles.icon} />

参考

https://stackoverflow.com/questions/68339712/chakra-ui-image-component-not-recognizing-image-path


githubのリモートリポジトリのプッシュ手順

https://qiita.com/sayama0402/items/9afbb519d97327b9f05c

接続リポジトリの確認と削除
    git remote -v
    git remote rm origin
    

ローカルでサーバーは複数立てられることを知った。。


node.jsでテストする時には環境変数をdotenvパッケージをインストールすると便利(next.js,reactには関係ないところでのテスト)

https://www.wakuwakubank.com/posts/662-nodejs-env/