愛犬のLGTM画像を共有できるサービスをリリースした
はじめに
今回はうちの愛犬の写真をコードレビューのLGTMで使用ができる & LGTM画像ジェネレータをリリースしましたのでそれの宣伝も含めた記事です。
コードレビュー時にLGTM画像として愛犬(きなこ🐶)の写真を使用できるサービスです。使いたい画像をクリックするとMarkdown形式でコピーすることができます。画像を投稿すると 「LGTM-kinako」 と画像を加工できます。
サービス概要
DarkModeに切り替えることもできます😈
リポジトリ
気に入っていただけたら⭐️していただけると励みになります🙇♂️
Frontend:
Backend:
技術スタック
技術選定の方針としては学習的側面が強いですが、サービスとしてある一定の品質を保てるように考慮しています。ランニングコストは極力抑え、長期的に持続可能なサービスを目指しています。
フロントエンド
- TypeScript
- Nuxt
- Vue
- Pinia
- Storybook
- TailWind CSS
- Vercel
- CircleCI
バックエンド
- Go
- Echo
- MySQL
-
PlanetScale2024年3月にTiDBに移行 - TiDB
- Render
- AWS
- CircleCI
その他
- UptimeRobot
- Google Analytics
- Search Console
サービス構成図
機能一覧
機能 | 概要 |
---|---|
画像一覧 | LGTM画像の一覧表示。画像をクリックしてマークダウン形式でコピー |
タグ絞り込み | タグを選択し検索する |
画像投稿 | 画像を投稿し、「LGTM-kinako」と加工する |
複数言語対応 | SEOのために英語対応 |
DarkMode | UI・UXの向上のためダークモード切り替え |
ダッシュボード | 管理者権限。画像の作成・削除 / LGTM画像の作成・削除 |
登録・ログイン | 管理者権限を使用するためにログインする必要がある |
開発のきっかけ
私は普段フロントエンドエンジニアとしてReactNativeでモバイルアプリの開発、Nuxtでwebアプリの開発をしています。最近はバックエンドの開発もさせていただいているのでGoを触る機会を増やしたいと思い簡単なアプリケーションを作成しようと考えました。
ではどんなサービスを作るのか・・・
唐突ですが、私は世界で一番尊い生き物と暮らしています。そんな可愛い生き物を共有したいと思いました。しかし、急に「うちの愛犬可愛いでしょ?」と送るわけにもいかず悩んでいたところ
「良い口実はないか...そうだ。PRのレビューの際にLGTM画像で送ればさりげなく見てもらえるぞ👏」
といった感じでサービス内容を決定しました。
個人開発で気をつけたこと
- モチベーションの低下を防ぐために自分が使用できるサービスにする
- 最小の機能を最短で開発する
- 拡張容易性が高いアーキテクチャ
モチベーションの低下を防ぐために自分が使用できるサービスにする
サービスを作る上でペルソナは重要です。しかし今回の個人開発ではペルソナの課題解決の側面よりも勉強のためというのが強いため持続的な開発が効果的だと思いました。その上でペルソナを練るよりも自分そのものがペルソナになるサービスが継続率が高いと思い自分が使用できるサービスを作成することでモチベーションの持続を計りました。
結果実務でコードレビューの際にLGTMにきなこの画像を使用することで作る意義というのを意識的に作ることができました。
実際に多くのユーザーさんに使用してもらうのはとても素晴らしいことですが、それなりに体力も使うのでミニマムで始めたい人は自分で使用する前提のサービス(他の人も使用できる)を開発するのは個人的におすすめだと思いました。
最小の機能を最短で開発する
以前有志で集まったメンバーとチーム開発を2年程していたのですが、学びはあったもののリリースまでできず開発を終了してしまいました。なぜ途中で終了してしまったのか。それは各々の「勉強したい技術」や「改善したい機能」があり、リプレイスを繰り返すような結果になってしました。
なので今回はその反省を踏まえて小さい機能でもよいからまずはリリースをするというのを目的の1つに添えて開発をしました。
拡張容易性が高いアーキテクチャ
機能をはじめから多く設計してしまうとリリースまでの道のりが長くなってしまいモチベーションに影響が出ることがあります。実際のビジネスの場では顧客の要望や運用最低限の機能を考える必要がありますが、個人開発ではよく悪くも自分が線引きを引けるため決めの問題になります。今回は機能を小さく作成し後から追加できるような設計思想を意識して開発していきました。
フロントエンド
フロントエンドの設計思想は Feature型のディレクトリ構造を採用しました。以下で記事を書いているので気になった方は以下を見ていただけたらと思います🙇♂️
バージョン情報
- Node.js v18.18.0
- Nuxt v3.6.5
- Vue.js v3.2.36
- pnpm v8.13.1
- TypeScript v5.2.2
使用技術
Nuxt
実務でも使用していますが、最近はReactNativeに触れる機会が多くVue3で追加されたscript setup構文に慣れる目的も含めてNuxtを採用しました。関心ごとに分離させやすい構造だなと改めて感じました。
Tailwind CSS
Tailwind CSSは汎用的なユーティリティのクラスが用意されているため便利なのはわかっていたのですが、インラインでstyleが長くなってしまうのがいまいち慣れなく実際に使用する機会がなかったので今回採用して見ました。
pnpm
npm、yarn と並ぶ JavaScript のパッケージマネージャーのpnpm(performant npm)を採用しました。アプリケーションから直接参照するパッケージを限定的にする思想にとても魅力を感じていたので決定しました。
具体的には以下のような強みがあります。
-
効率的なストレージ使用する
同じパッケージの複数のコピーを保存する代わりに、シンボリックリンクを使用して一意のパッケージインスタンスを参照します。これにより、ディスクスペースが節約されます。 -
厳格な依存関係
プロジェクトが宣言していない依存関係にはアクセスできないようにします。これにより、意図しない依存関係の使用を防ぎ、より安全な依存関係の管理を促進します。
StoryBook
コンポーネントのカタログ
バックエンド
バックエンドの設計思想は、ドメイン駆動設計(DDD)の概念を取り入れた構造にしています。usecaseはドメインロジックの中心部が集まるので、保守性のため1ファイル1メソッドにしました。複雑なDB構成にならない想定のためマイグレーションはgormigrateを採用しました。
バージョン情報
- go 1.20.7
- echo v4.11.1
- mysql v8.0
- gormigrate v2.1.1
使用技術
Go
今回勉強の主軸に置いたのがGoです。実務で最近はGoを書く機会が増えたので手を動かせる機会を増やしたく採用しました。
MySQL
CloudのMySQLサービスを触って見たいと思い、MySQLとPlanetScaleの組み合わせを採用しました。
PlanetScaleはMySQLをベースとしており、特にスケーラブルで信頼性の高いデータベースソリューションを提供する分散型SQLデータベースサービスです。
しかし、以下のようにPlanetScaleのHobbyプランが2024年4月8日に廃止してしまうので移行先は検討中です🙇♂️
その他
使用技術
マーケティング
今回は数値の分析も行える体制を整えるため以下のマーケティングをツールを採用しています。
- Google Search Console
- Google Analytics
本来は「LGTM 画像」で上位検索を狙いたかったですが、古参のサイトが数多くあるため今回は「LGTM 犬」や「LGTM 動物」での上位検索を目的としたSEO対策をしています。
その対策として以下を対応しました。
- 上記キーワードを狙って基本的なtitle, descriptionの整理
- vue-i18nを使用しより広いターゲットオーディエンスに適用するため英語対応
UptimeRobot
インフラの構成で使用しているRender.comには無料プランによる制約がありました。今回その解消のためにUptimeRobotを採用しています。UptimeRobotは元々監視ツールですのでその用途でももちろん使用できますが、今回はRenderの「非アクティブな状態が15分間続くとスリープ状態になってしまう」という欠点を解消するために使用しました。
APIに定期的にリクエストを送ることで一定期間非アクティブな状態を作らないようにしました。
Render.com無料プランのスリープ対策の記事を参考にさせていただきました。
最後に
まだまだ追加したいができていない機能や勉強のために作ってみたい機能などあるので今後も気長にサービスを成長させていこうと思います。
是非コードレビューの際に愛犬のきなこの画像を使用いただければ嬉しいです🐶✨
Discussion