メンタル向上特化型日記アプリ『3 Good Things!』をリリースしました！【個人開発】



# 『3 Good Things!』とは？

![3gt_main (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/5e06a51b-d4d7-7620-25ab-17fd10b94b72.jpeg)

ポジティブ心理学[^1]の創設者セリグマン教授が提唱し、長年の実験で効果が実証されている “Three Good Things”メソッドを使い、毎晩5分の習慣で考え方をポジティブに変えていくためのアプリです。(*PWA対応Webアプリ)

具体的には、とても簡単で、**今日あった良かったこと3つをアプリに記録するだけ**です！

👇**利用はこちらから。登録不要のデモも出来るので気軽に試してみてください**🙏

https://www.3-good-things.app/

🎨**追記：UXデザインの際に勉強したことを別の記事でまとめました**📈

https://qiita.com/herishiro/items/1f595fcd19e369c5895c

🐙レポジトリはこちら🐈

https://github.com/herishiro/3-good-things_pub

[^1]: ポジティブ心理学とは、健康な人も含めて精神的に安定したより良い生活(well-being)を送る方法について心理学的なアプローチから研究する心理学の一分野です。[ポジティブ心理学とは - 一般社団法人日本ポジティブ心理学協会](https://www.jppanetwork.org/what-is-positivepsychology)

# 自己紹介と作った背景

現在インハウスのWebデザイナーとして都内の中小企業に勤めています。
が、元々は新卒から事務員を数年して、そこで知ったExcelマクロの面白さからWeb業界への転職を決意したのもあり、
今後はプログラミングを主業務として働きたいと考えています。
その転職活動の一環で今回のアプリを作成しました。

ちなみに事務作業のめんどーーーさが骨身に染みてるので、
特にバックオフィス効率化を主軸にした「ユーザーが面倒にならないサービス設計」と、「作る側が面倒にならないコードの品質管理」に興味があります。

業務でVueとNuxt.jsを使ったことがあるのですが、
上記のようなバックオフィス系のサービスを開発している会社のエンジニア募集要項を見るとReactが優勢に思えたので、今回は未経験のReact(Next.js)を選択しました。

### 題材にThree good thingsを選んだ理由

正直去年、某パンデミックで相当精神的にグエーーーとなっている時期があり、
色々とメンタル立て直しを図る中で実践していたのがこのメソッドであり、その時は単純にスマホのメモ帳に毎日記録していました。（今は滅茶苦茶元気になりました）

ただ実際には「細かく質問項目に沿って記入していった方が効果がある」（というか実験はそういう形式で行われた）と書かれていたので、
正しいやり方で記入できるフォーマットのあるアプリがあれば良いのになと考えていました。

しかしこの手のアプリは**ベースに面倒臭さがあるので**、極力「頑張ってやらなくてはダメ」という圧を排した気軽にできるものである必要があります。

機能としてはかなりシンプルで、正直技術的に見るべきものはないかもしれませんが、
自分のプログラミング経験の浅さを考慮しつつ、「ユーザビリティの追求」を提示できそうなテーマだと考えて、このアプリを作ることにしました。

# 機能・特色

日記好き（しかし継続できない）の立場から考えて、

- 「今日何があったか思い出せない」
- 「書くほどのことは無かった気がする」
- 「そもそも入力が面倒くさい」

という気持ちを日記アプリ最大の障害として課題設定しました。

**そして、それを乗り越えるお手伝いとして、『3 Good Things!』は下記の機能を提供しました👍**

- **手元のボタンをクリックするだけで入力が完了！めんどくさいことなし！**
- **カテゴリやリストのサジェストで今日あったことが絶対思い出せる！**

#### 実際の入力画面
カテゴリーを選んで、カテゴリごとのリストに今日良かったことがあれば、なんとタップするだけで入力完了🎉
![3gt-input-flow.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/2c13af3d-ff0b-9816-2434-3951f57151a9.jpeg)


##### 動画版
【カテゴリーから適当に気になるのを選んでみて】
![Image from iOS (1) (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/f600a2be-4bdc-ea11-7257-8942290aeb93.gif)


【カテゴリー選択後の幸せリストから、似たような幸せがなかったか考えてみよう！】
![Image from iOS (3) (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/6800df1b-f68a-f227-b34e-83e4e70c00f2.gif)


# 使用技術

基本的にフロントエンドはNext.js + typescript、バックエンドや認証周りはfirebaseを利用して、vercelにホストしています。
ログイン回りの挙動はjest + playwrightによるUI testingを実施して、関連部分の修正で致命的な不具合が出ないよう、安全に開発できるようにしました。

- typescript 4.3.2
- React 17.0.1
- Next.js 10.2.0
- next-pwa 5.2.21
- material-ui 4.11.3
- @reduxjs/toolkit 1.5.1
- firebase authentication/ firestore
- jest 26.6.3
- playwright 1.11.0

### React & typescript

私はフレームワークとしてVueとReactどちらが好きとも嫌いとも言えませんが、本格的にTypescriptを使って開発するにあたって、Reactのtsとの相性の良さはやはり強いアドバンテージだと感じました。
(typescript自体は以前からAWS Lambdaなどと連携したアプリでNode.jsを書く時に使用していました)
業務の方ではNuxt+javascriptでアプリケーションを作ったのですが、一応lintなどは付けて使っていても、、、それと比べ今回は格段に心穏やかに開発出来ました笑
多分これはNuxtのせいではなくjavascriptの方に原因があったと思います。
ランタイムエラーが減るとここまで精神的に落ち着いて開発できるのかと正直感動しました😊🤟

### Next.js & vercel

今回は基本的に静的ページ+クライエントサイドレンダリングで作成したのでSSGやSSRといったNext.jsの機能を活用出来たとは言えないのですが、公式の丁寧なチュートリアルも含めて使いやすいなと思いました。
ただしフォルダ構成についてはNuxtほど細々プリセットが用意されていないので、最初に自分で参考記事を読んで構成を考えなければいけない難しさがあります。
というかNext自体、Nuxtよりも最初からアレコレ指図してこない代わりに、自分で必要なものをカスタマイズしていく力が要求される傾向があると感じました。

一番Next.jsにして良かった！と思ったところは正直vercelですね。
vercelはNext.jsを開発している会社であり、Next.jsで作られたサイトに最適化されたホスティングサービスでもあります。

- **メインブランチを自動でデプロイしてくれる上、全ブランチも個々にURLを自動生成して実際にサーバー上で動かしてでチェックできる**
- **他で買ってきたドメインを登録するだけで超簡単にSSL認証書の発行やリダイレクト設定をしてくれる**

この2点が最高でした！しかもアクセス数などは関係なく一通りの機能は無料！あんまり使いこなしてないけどパフォーマンスインサイトも無料！
インサイトがアカウントにつき1個しかactivate出来ない以外では、今のところ無料の制限を感じたことはありません。

そのため、firebaseの方の無料枠で使われる限りは、このアプリにはドメイン代しかかかりません。

### Redux Toolkit

Nuxtからやってきた民としては、本体にストア機能が付いてないのは、えっ！？という気持ちで最初、じゃあ作り出す前にReduxも勉強しなきゃと思いました。
しかし調べていくと、今はuseReducer&useContextなどを使って本体の機能でも代替できる上、Reduxはややこしいから好きじゃないという意見が多く、、
とりあえずNext内製機能でやっていくことにしました。

しかしContextが4種類程になってきたあたりで管理に限界を感じたため、redux-toolkitの導入に舵を取りました。

その結果、最初から入れておけば良かったなと思いました笑

#### チュートリアルが凄く良い

https://redux.js.org/tutorials/essentials/part-1-overview-concepts

新しい技術に触れる時は基本的に公式チュートリアルをやってみるタイプなのですが、Redux(redux-toolkit)のチュートリアルは今までで一番素晴らしいと思いました。
ただ、難点もあります。親切丁寧という意味では基本親切な割にいきなり端折ったりしてくるので、ガチのプログラミング初心者にはキツイ感じがしました。
（Next.jsのチュートリアルはそういう意味で本当に親切でした）

しかしダウンロードするだけで仮想データベースごと立ち上がってRedux以外のことは気にすることなく、全部の機能を極めて分かりやすく、かつ実践的に学べるのでやりごたえがあります。
また単なる使い方を超えて、ストアの設計思想ごと勉強できるので、私のような独学者には大変ありがたかったです。

#### デベロッパーツールが死ぬほど良い

chromeの拡張機能でReduxのツールを入れるとどうなるかというと

- 例えば一個のユーザーのクリックに対して複数のアクションがステートに起きる時、その全てをトレースできる
- 一つ一つアクションの発火をさかのぼって、どのアクションでどこのステートが変化したのかが一目瞭然
- デベロッパーツールのくせにとにかくUIが良くて分かりやすい

UIはこんな感じ。
Diffというタブではそのアクションで動いた値だけを表示してくれます。
上のスペースはアクションのスタックになっていて、いくらでも遡って処理中ステートに何が起きたか調べることが出来ます。

![スクリーンショット 2021-06-26 151849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/83689830-8f5b-0377-5196-4df154362c83.png)

バグ修正でこいつに何度助けられたことか…

#### UIコンポーネントとステート管理ロジックを綺麗に切り離せる

Nextに内蔵されているuseReducer&useContextコンビも単純にステート管理という意味では悪くないのですが、基本的に「非同期処理には使えない」という弱点があります。
その結果、Reduxを使う前は、DBとの通信などのデータの起点や終点となる処理は置き場所が定まっておらず、Pageフォルダ内のPageコンポーネント内に散らばっていました。

それに対してReduxはAsyncThunkという機能で非同期処理も一手に引き受けてくれます。
そうしてステートに関する関数自体はsliceファイルに置き、その関数を呼び出してステートを更新するロジックはproviderコンポーネントに分離したことで、UIコンポーネントはステート管理から極力切り離されて凄くコードがクリーンになりました（当社比）
（なおproviderコンポーネントは_app.tsxのrootコンポーネントから呼び出します）

---
以上の理由から私は、それほど大きくない個人開発でもRedux-Toolkitの導入をお勧めしたいです。
確かに新規な概念が色々と出てきて学習コストはかかりますが、それも昔複雑さで忌み嫌われていた時代と比べるとtoolkitの開発で大分シンプルになったようですし、コストを補う強力さがあると思いました。

### jest & playwright

前々から「テスト駆動開発」って良さそう…やってみたいな…と思っていたのですが、
今回ログイン/アウトの挙動が実装中「あちらを立てればこちらが立たず」という状態になり、少しコードを弄っては手動で確認する作業に限界を感じたのを良い機会に勉強することにしました。

まず古典「テスト駆動開発（Kent Beck著, 和田 卓人訳）」をJavaが分からないながらに読んでコンセプトを理解したのち、
jestとplaywrightを導入して、真似事レベルですがテスト駆動開発をやってみました。

UIコンポーネントをテスト駆動開発するまでには至らなかったので今後の課題ですが、ステートや外部DBに依存しないヘルパー関数でいくつかテスト駆動開発を行いました。

コンポーネントに紐づける前に、引数に対して意図した処理が行われるかの確認を取りながら開発を行えるのはそれだけで心理的負担が低く、
もっと気軽に包括的に実践していけるよう今後も取り組んでいきたいです。

余談ですがツールや方法論とは別に「テスト駆動開発」にはエンジニアが根気よく最短距離で開発をする心構えが説得力を持って書かれており、内容が古くならないタイプの本だったので読んで本当に良かったです。

### PWA (Progressive Web Apps)

現状はハッキリ言って対応した「だけ」という感じです😅
ただ今後ネイティブアプリに置き換えない方向で拡張することにした場合、通知機能など欲しい機能が提供されているので、ローンチ前に仮でも対応させておいた方が良いだろうと考えました。
ただ現状でも、

- ホームスクリーンに設置してネイティブアプリっぽい広い画面で快適に使える
- ホームにあるだけで存在を忘れられにくい

という利点があると思います

余談ですが、自分はずっと思考停止系iPhoneユーザーだったんですが、PWAの機能見てるとandroidに乗り換えよっかなって初めて思いましたね…😊💧

# 今後追加したい機能

### SNS連携機能

これはローンチして数日たってみて、今後ユーザーを増やしたいのなら急務だなと感じています。
昨今、何か無名のサービスを多くの人に使ってもらおうとしたら、どんなアプリでもSNSの拡散力を利用しない手はありません。
なのでそもそも「あった方が良いだろうな」とは思っていました。
しかしローンチ後ターゲット市場をリサーチしたところ、こういう健康法が好きな自分すら予想してなかったんですが、Twitterで検索すると毎日何十人もの人が関連タグを付けてこの「Three good things」メソッドを実践して呟いてるんです！
考えてみるとメソッドの性質上、入力した内容を周りにシェアしたくなる、SNSと相性のいい類のアプリなんですよね。

このアプリに記入したことをそのままTwitterやFBに投稿できるようにして、その中の数人でもこのアプリから投稿してもらえれば、それだけで宣伝になるでしょう。
そうでなくてもまず私がタグ付けてアプリから投稿すれば宣伝になります笑

そんな感じで一通りのローンチ対応が終わったら着手すべく、どうやって投稿内容を生成するか今考え中です（Twitterに収まらない字数なので、公開用リンクを用意するか、質問系みたいに画像を生成するか…）

### カスタムよかったことリスト

要するに自分用の「良かったことショートカットリスト」を登録できる機能です。
これは結構簡単に付けられる機能の中で、テストユーザーに需要が多かったので、手が空いたら付けたいです。

### リマインダー

自分で使ってみても思いますがこの手のアプリ、やはり使うのを忘れて寝てしまいます。
他の先行のネイティブアプリを見てもリマインダーは必須という感じがしますが、なにせWebアプリ…ただandroidであればPWAの機能でプッシュ通知が出来るので、それだけでも付けたほうが良いと感じています。（問題は私がandroid持ってないというところですが）

### 脳の報酬系向け機能の充実

毎日続ける！という決意に対してアプリの方からなにか出来る事あるとしたら、まめに達成度を示してモチベーションを維持させてあげる事ではないでしょうか。
現状「連続○○日達成中！」が一覧ページに表示されるようになっていますが、
本格的にやるなら、もっといろいろなアクションに対して反応を返し、何か素敵な見返り（アプリ内でおまけ機能が解放されるポイントとか？健康TIPSとか？）を用意するなどの施策をするべきだと考えています。


# 初めて個人開発アプリを完成させてみて

面白かった、の一言に尽きますが（まだ全然終わってませんが）
あまりSNS等を介して他の開発者と交流せずにやってきたので、今更色々他の人のを見てみていると、SNSのような複雑なアプリを他の仕事をしながら短期間で作っていてすごいなぁと思いました。
可処分時間に差があるので単純比較はできませんが、自分は大分開発期間長い方だと思います。

自己分析してみて、長く時間がかかったのは、まずReactやNext.jsに初めて触れて作ったというのもありますが、
作り始めてから大きい変更や要件の追加を行ったからというのもあると思います。
思い出せる限り、メインコンテンツが大体完成した後にこれだけの変更をしています

- 知り合いのアドバイスを元にUIを大幅変更
- ステート管理をReduxに移行
- testingについて一から勉強して導入

これ以外にもローンチ前に知り合いの指摘を受けてもっともだと思った機能を複数個追加しています。
（連続○○記録欄や、ログインチュートリアルなど）

これらは要するに初期の要件定義が甘かったとも言えますが、
個人的な方向性として「最初から何でもやろうとしないで、後での変更に強いコードを書こう」ということにしてました。
結果としてそこの観点からもReduxは最初から使うべきだったと思いますが、
その他の変更については初期からコンポーネント間の依存性を低くするよう意識して作っていたので、
要件が加わってもやる気が削がれることなく開発を続けることが出来、なんとか完成させることが出来ました。

途中まで先行アプリの研究すらしないで作っていたのですが、正直完成したネイティブアプリを最初から研究していたら、
自分に対する要求が高くなりすぎてもっと出足が重くなってたんじゃないかと思います。

---
どうでもいいんですが、作り始めた時から8割くらいまではずっと「この作業無限か？」と思いながら作業してるけど、終わるときは突然終わる感じが同人誌作りに似てるなと思いました。

ここまでお読みいただきありがとうございました！