🌊

【個人開発】2000RT超えの大バズリ〜初課金まで至った穴埋めテストメーカーを支える技術

2022/12/01に公開

この記事は個人開発Advent Calendar 2022 1日目の記事です。

2022年6月13日、私が個人開発でリリースしたサービス「テストメーカー」がTwitterで2,000RT、7,600いいね以上の大バズリを記録しました。

https://test-maker.app/

https://twitter.com/Meijin_garden/status/1536136768583507968

「テストメーカー」は穴埋めテストを直感的に作れるツールです。
マウスで穴埋めにしたいテキストを選択して離すと、その部分が穴埋め問題に変わります。

create-test-image

リリース以降、主に全国各地の中学校、高校、大学などの授業で使っていただいたりしながらユーザー数が増えています。
他にも、社会人の方が国家資格を受験するときの受験勉強に使っていただいていることもあります。
ITMediaさんに取材も受けました。

https://www.itmedia.co.jp/news/articles/2206/14/news126.html

そして、リリースからおよそ1ヶ月が経過した7月に課金機能を実装し、そこから少しずつですが課金してくださるユーザーさんも増え続けています。

本記事では、そんなテストメーカーを支える技術スタックを中心に、開発のきっかけや進め方、初課金に至った経緯、リリース後の機能追加などについても書いていきたいと思います。この記事が個人開発にこれから取り組もうとする方や、すでにいろいろ悩みながら取り組んでいる方になにか参考になれば幸いです。

本記事でお話すること

以下の順でまとめていくので、気になるセクションからご覧いただいても大丈夫です。

  • テストメーカーの主な機能
  • テストメーカーを支える技術(テクノロジー編)
  • テストメーカーを支える技術(プロダクトマネジメント編)
  • まとめ

テストメーカーの主な機能

技術スタックを解説する前に、テストメーカーにはどんな機能が実装されているかざっくり説明していきます。早く技術スタックについて知りたい方は次節まで飛ばして読んでください。

テストメーカーにログイン(Googleログイン)していただくと、以下のような画面が開きます。

test maker screen shot

画面左上のボタンからテストを作ることができ、作ったテストは左中央部分にリストとして並んでいきます。各テストをクリックすると画面中央部分にタイトルと本文が開き、編集可能になります。
画面左にデータの一覧が並び、クリックすると各データが開けるUIはNotionを参考に考えています。

そして再掲となりますが、穴埋めテストにしたい単語をマウス操作で選択して離すと、その瞬間に穴埋め問題に変わります。

create-test-image

ちなみにソースコードの挿入(「`」3つで挿入できます)と、ソースコード中の穴埋め問題にも対応しています。Reactの公式ドキュメントをWebからそのままコピペしてテストにすることも可能です。

ezgif com-gif-maker (15)

この快適な操作感は体験していただくとより伝わると思うので、お時間のある方はぜひテストメーカーにログインしてテストを作ってみてほしいです(基本的な機能は無料で使えます)。

https://test-maker.app/

テストメーカーを支える技術(テクノロジー編)

まずはテストメーカーを支える技術のうち、具体的なテクノロジー(フロントエンド、バックエンド、インフラetc)について説明します。
そのあとプロダクトマネジメント(短時間で開発するコツ、課金プランの考え方etc)について説明していきます。

技術選定の全体感

個人開発であるテストメーカーの開発においては、以下のことを意識して技術選定しています。

  • 基本的には自分が慣れているものを基準に選ぶ
  • 慣れていない技術であっても、開発速度が向上するものであれば積極的に選ぶ
  • サービスの肝になる部分については触ったことのない技術にチャレンジ

個人開発プロジェクトが頓挫する理由の個人的な第一位は時間がなくていつまでも完成しないことです。それを防ぐために、基本的には自分が慣れている技術を選ぶべきでしょう(Next.jsなど)。
とはいえ技術的にまったく新しいことがなければ飽きてしまってやめる可能性もあります。そこで私は慣れていない技術でも、開発速度が(一時的であっても)向上するものは採用するように割り切って開発を進めました(daisy UI、frourioなど)。
そして、サービスの肝になる部分については触ったことのない技術にチャレンジしました。テストメーカーではWYSIWYGライブラリを使う部分が肝です。これまで実務で触ったことのあるライブラリやそれに類似したものからは選ばずに、要件をより満たせる可能性の高いものを選びました。

フロントエンド

Next.js(React)

テストメーカーのフロントエンドにはNext.jsを使っています。Next.jsは言わずと知れたReactベースのWebフレームワークです。

https://nextjs.org/

選定した理由は、

  • 後述するWYSIWYGライブラリを選定するときにReactが一番豊富そうだと思った
  • 自分がReactに比較的慣れている
  • 自分がReactフレームワークの中ではNext.jsだけ経験があった
  • 後述するfrourioというバックエンドフレームワークとの組み合わせがしやすかった

あたりが主な理由となります。

デプロイ先はVercelです。

WYSIWYGライブラリ(contenteditable)

続いてテストメーカーを開発する上で目玉となるWYSIWYG技術について説明します。

WYSIWYGとは「What You See Is What You Get」の略で、文書を作成できるソフトウェアの特性のうち、最終的な見た目を画面上に表示しながら編集できる技術のことを指します。

たとえばWordやNotionで文字を入力している最中は、入力したと途端に最終的な見た目に変換されながら入力できます。
そういった技術をWYSIWYGとよび、また、WYSIWYG技術を活用したエディタをWeb上で簡単に構築できるライブラリがいくつもリリースされています。

ライブラリの例としてはDraft.jsLexicalCodeMirrorSlateCKEditorなどがあります。

テストメーカーではエディタで文字を入力し、穴埋めにしたい箇所を選択してマウスを離すとその瞬間にその場所の見た目が穴埋め問題に変わることから、WYSIWYGであることが必須要件でした。
実際は大半のライブラリで要件は満たせるかと思いますが、ドキュメントを一通り読んでやり方がイメージできたライブラリを選びました。

また、WYSIWYGライブラリは普通のWebサービスとは異なり、DOM要素をそのままWeb上で編集できる特性を持っています。
こういったWebサービスを開発するには、Contenteditableとよばれる技術を活用することが必要です。

https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/contenteditable

contenteditableについて知っておくと、テストメーカーのようなWeb上で柔軟にテキストを編集できるサービスを作ることができます。

aspida/pathpida

テストメーカーはバックエンドへのアクセスにREST APIを使っているのですが、REST APIを型安全に扱えるaspidaというライブラリを使っています。

https://zenn.dev/solufa/articles/getting-started-with-aspida

続いて、Next.jsにおいてサイト内リンクを実装するときに、URLを文字ベースではなくて型安全に実装できるpathpidaというライブラリも活用しています。

https://zenn.dev/solufa/articles/renewed-pathpida

これらは同じ作者さんの実装で、似たような開発者体験で開発することが可能です。

Tailwind CSS(daisyUI)

テストメーカーのスタイリングはTailwind CSSとdaisyUIを使っています。

https://tailwindcss.com/

https://daisyui.com/

Tailwind CSSはCSSのクラス名の名付けから開放してくれることから、開発スピードの向上やコード品質の平準化に貢献できるライブラリだと思っているのですが、それだけだと個人開発ではUIパーツが揃っていないため開発に時間がかかってしまいます。

MUIなどとの併用も検討しましたが、試しにdaisyUIを使ってみることにしました。

daisyUIはTailwind CSSをベースにしたUIライブラリで、たとえばbtnというクラスを当てるだけで当てたDOMがボタンの見た目として完成します。
CSSだけでいろいろなUIが完結しているところが面白いです。たとえばモーダルすらもJS不要で開発できます。

https://daisyui.com/components/modal/

react-table(TanStack Table)

テストメーカー内で、各テストの回答履歴を一覧できる機能があるのですが、表形式で閲覧できるので表をコーディングするのがちょっと面倒でした。

そこで、react-table(TanStack Table)とdaisyUIを組み合わせることで簡単にテーブルを作成しました。

https://tanstack.com/table/v8

https://daisyui.com/components/table/

react-tableはテーブルにどんなデータをどういった形状で表示するかや、テーブルを構成する各Element(<table><tbody>など)にどんなPropsを渡すかを責務として持っており、スタイリングはTailwind CSSなどのCSSソリューションで好きに行うことができます。なので、react-tableでロジック部分を組んで、daisyUIのtableクラスでテーブルのデザインを当てました。

vitest

テストメーカーはさほどロジックを持っていないアプリケーションなのですが、コアな部分だけテストコードを書いています。
フロントエンドもバックエンドもTypeScriptなので、Vitestをテストランナーにしてテストを書いています。

https://vitest.dev/

jest(+babel-jest)よりテスト実行速度が比較的速く、セットアップも非常に簡単です。Vitestの元になっているVite自体がアーリーな技術なので、業務での採用は少々慎重になる必要がありますが、個人開発なので使おうかなと思ったのと、APIがjestとかなり近しいので、最悪jestに戻せるかなとは思っています。

サーバーサイド/インフラ/PaaS

テストメーカーはフロントエンドメインのアプリケーションなのでフロントエンド部分を手厚く解説しました。続いてバックエンドについて簡単に説明していきます。

frourio/fastify/Firebase/Railway

バックエンドではフレームワークにfrourio、WebサーバーにFastify、認証にFirebase、サーバーのホスティング先にRailwayを使っているのですが、こちらは以前まとめた記事があるので気になる方は読んでいただければと思います。
frourioは型安全かつ爆速にREST APIベースのアプリケーションを構築できるフレームワーク(とても薄いのでほぼCLIツール)です。
Railwayは個人開発サービスのバックエンドのデプロイ先として結構優秀だと思います。とにかくお手軽に使えます。ドキュメントも平易です。

https://zenn.dev/meijin/articles/frourio-firebase-auth-railway

上記記事への追記としては、実運用したところ、Railwayのサーバー費用に月あたり$30くらいかかっているので、正直フルFirebaseでやったほうが安いです。
ただ、今回はRDBで開発したかったので、RDBで個人開発で良い感じの管理画面でDockerfileベースでデプロイできるサービスとしてはRailwayはめっちゃ有力だと思います。

あと、frourioの利用に伴ってORMのPrismaを初めてまともに触ったのですが、マイグレーションから型が自動生成されるのがとにかく快適で、個人開発×RDBにはうってつけだと感じました。

Stripe

テストメーカーは2022年12月現在、月額399円の有料課金プランがある(基本機能は無料です)のですが、課金機能をStripeで実装しています。
サブスクリプション機能の実装は考慮することが多く骨が折れます(本業でPAYJPを使った月額課金サービスを開発していますが、大変です)が、StripeとFirebaseを組み合わせたExtensionを使えば、かなり簡単に月額課金機能を構築できます。

https://qiita.com/mogmet/items/cddc182156028c928ecf

もちろんデメリットもあって、サブスクリプションのステータスがFirestoreに保存されるので、RDBベースのバックエンドと組み合わせて使うには、バックエンドからFirebase Admin SDKを使ってFirestoreを読み取ってサブスクリプションがActiveか判定しないといけません。このへんの実装に不安がある方は、このExtensionを使わないか、バックエンドをフルFirebaseにするのがいいでしょう。私も正直RDBとFirestoreの組み合わせを実務で使う気にはならないです。

その他

ezgif

ezgifというサイトがありまして、GIF画像を作成するのに便利です。トリミング、スピード変更、軽量化などいろいろな編集操作ができます。
テストメーカートップページのファーストビューにある操作イメージのGif画像はこのサイトで作っています。

https://ezgif.com/

この情報は以前Twitterで@mascii_kさんから教えてもらいました。ありがとうございます!

https://twitter.com/mascii_k/status/1493528172327215105?s=20

Fluent Icons

アイコンはFluent Iconsというサイトからいつも拝借しています。

https://fluenticons.co/

アイコンの種類が多いのはもちろんのこと、一番嬉しいのがCopy as SVGできることです。個人開発ではデザインをサボりがちですが、これで気軽にデザインのあちこちにアイコンを設置できます。色はcurrentColorにして親クラスでTailwind CSSで色を指定すればよいです。


以上でテストメーカーを支える技術のテクノロジー編を終わります。

テストメーカーを支える技術(プロダクトマネジメント編)

続いて、開発以外の進め方や仕様の決め方といった部分について、プロダクトマネジメント編としてまとめていきます。

初期リリース時点での機能は厳選する。課金機能も後回しでOK

初期リリース時の機能はこれでもかというほど厳選しました。
マウスで選択したところが穴埋めになる方法でテストが作成できる、URLを共有することで回答してもらえる、回答したら自動で採点できる、採点結果はテスト作成者が一覧で見れる、以上!という感じです。
逆に後からリリースした例でいうと、課金機能、選択問題の作成機能、回答時に名前を記入できるようにする機能などがあります。

ちなみにテストメーカーは開発を思い立ってからリリースまで半年間かかっています。もちろん本業などもあるので半年間そのまま開発しているのではなく、ゴールデンウィークや3連休などに集中して進めて、また寝かせて、という感じで進めています。リリース後もそんな感じです。ですので、技術選定もそうですが、限りなく時間を使わずに開発できるように仕様面と技術面の両方から全力で工夫するのが大事です。

課金機能も後回しでよかった、という点について詳しく補足します。
無料では「テストを作成できる個数が20個まで」という制限をかけていたのですが、リリース当初は「20個テストを作ると、画面左上に警告が表示される」というもので、その内容は「無料版ではテストを20個までしか作成できません。有料版をご利用の方はsupport@test-maker.appまでご連絡ください」でした。

つまり、技術的に自動で課金したら20個以上テストを作れるのではなく、興味のある方はこちらに連絡してね、という形式を取ったのです。
そもそもニーズがあるかわからない状態でリリースしているプロダクトアウトなサービスなので、リリース前から課金機能をせっせとこしらえても意味がありません。

そして狙い通り、リリースして3週間ほど経過したある日、メールアドレス宛に「有料版を使いたいのですがどうすればいいですか」という連絡が届きました!
その連絡を見てから、前述したStripe用のFirebase Extensionを使って課金機能をリリースして(もともと開発できる見立ては立てていました)、メールに返信しました。「有料版のご利用案内をしたいので、Zoomでミーティングさせてもらいませんか」と送ると、ご快諾いただいたのでその数日後の夜にZoomをつなぎ、リリースしたばかりの有料課金機能を説明しながらその場で課金を実行していただきました。ついでに、そのあと30分ほどどういう用途で使っていて、どうして20個もテストを作っていて、今後も使い続けたいと思っていただいているのかを聞きました。

この方法の良いところは、ユーザーインタビューもついでにできるし、動作確認もその時やってもらえるし、有料版のニーズがあるとわかってから開発できるなど沢山ありますので、個人開発のようなMVPのプロダクトではオススメかなと思います。

コア部分だけ開発してクローズドで披露→モチベUP

テストメーカーのリリースは2022年6月13日ですが、コアロジックとなる、「マウスで選択した部分が穴埋めになる」UIは2021年の年末に完成していました。つまり半年以上前ですね。

そのタイミングで、私が所属させていただいている個人開発者のコミュニティ「運営者ギルド」にて操作動画をシェアしました。

https://qiita.com/organizations/admin-guild

コミュニティ内の自分のSlackチャンネルにも当時数十人の方が入っていただいており、そのとき操作動画に対してこれはすごい!という反応をたくさん頂いたのを覚えています。

ログインやログアウトも実装していませんし、本当にマウスで選択してそこが穴埋めになる部分だけの開発でしたが、その反応を見て、これを形にしたいな、形にしたらニーズがあるかも知れない、と思うようになりました。

ということで、開発したいサービスがあったらよくあるログイン・ログアウトから実装するのではなくて、コア部分だけ実装して限られた人たちに見てもらうというのは大事かなと思いました。もちろん理想はターゲットユーザーに見てもらうことですが、テストメーカーのようにターゲットユーザーが絞りにくい汎用的なツールの場合でも、こういう方法で初期からモチベーションを上げて開発を始める方法があるという意味で書かせていただきました。

Twitterでバズるために狙ったこと

冒頭で説明したように、テストメーカーリリース時のツイートは数千リツイートを記録するほどバズりました。このとき心がけたことを簡単にですがまとめておきます。

  • ツイートは平日の朝イチにする(休日はタイムラインがアクティブではない。また朝にすると勤務前に見てくれて拡散されたとき拡散の猶予が1日分あるのが大きい)
  • 前述したezgifを使って、穴埋めの様子が簡潔にわかる操作動画を作成・添付する
  • 冒頭に【個人開発】とつけることで、
    • 本業関連のツイートではないことを明確にする(紛らわしいので)
    • エンジニアのフォロワーが多いので、拡散の初動を手伝っていただける(これが、先生の皆さんへ!みたいなニュアンスでツイートしちゃうと拡散の初動が悪くてまったくバズらなくて終わる)
  • ツイート内にどんな用途に使うことを想定しているかコンパクトにまとめる

https://twitter.com/Meijin_garden/status/1536136768583507968

トップページのデザインはベーシックに、内容は工夫して

トップページのデザイン自体はハッキリいってありきたりなものでいいと思います。

ただし、内容はファーストビューにGif画像を載せて「マウスで選択した場所が穴埋めになる」ことがわかるようにしたり、Googleログインのボタンも、「ログインする」ではなく「テストを作ってみる」という目的ベースの単語にしたり、中盤以降はテストを作る目的に応じて2種類のセクションに分けるなど、それなりに時間をかけて工夫しました。

ということで、デザインはいろいろなLPを見てありきたりなパターンを模倣しつつ、内容や文言はしっかりと厳選したものにするのがいいのかなと思います。

ログインはGoogleログイン一択!

テストメーカーではログイン方法をGoogleログインのみにしています。途中でメールアドレスログインにしようか迷った時期もありましたが、今となってはGoogleで良かったと思っています。パスワード再設定の実装も不要ですし、Firebase Authを使えば特に設定なしに非常に簡単な実装でGoogleログインが実装できました。

また、ログイン方式は1つでいいのかという問いについては、必要がないなら1つで絞っておくべきだと思います。認証方式は増やすのは簡単ですが減らすのは容易ではないからです。

肝心のニーズですが、リリースして半年ほど経ちますがGoogleログイン以外が欲しいですという要望は来たことがありません。
ちなみにユーザーのメールアドレスを見ているとgmail.comじゃないものも多いので、自分が思っている以上にGSuiteが普及しているのかなと思っています。

有料機能と無料機能について

2022年12月現在のテストメーカーの有料機能と無料機能の差異は以下のようになっています。

無料版の制限

  • テストは20件までしか作成できない
  • 回答履歴が10件までしか見れない
  • テストを記名式にできない(回答履歴画面で誰が回答したかわからない)

改めて見ると、無料でテストが20件まで作成できるのは優しすぎるのですが、これは最初リリース時に考えきれていなかった部分です。なので、ここは理想的には10とか5に設定するほうがいいと思っています(し、今後そうするかも知れません)。
逆に、回答履歴が10件しか見れない制限はすごく当たっていると思っていて、学校の授業で使っている方(≒仕事で教育に関わっているため、課金する動機がより強い方)は、一般的に10人を超える生徒さんに指導しているので、テストを記名式にしつつ、10件以上回答履歴が見れるという機能を開放したくなります。

なので、考え方としては、プロダクトアウトなサービスを一旦リリースしてみて使われ方を観察し、お金を払っていただけそうなユーザー像を考えた後、そういった属性のユーザーさん特有のニーズを有料機能として提供したのが良い感じだったかなと思います。

また、選択問題を作成できる機能を10月頃にリリースしたのですが、テストメーカーが使える科目の幅を広げたという意味で、遠回りに有料課金率改善に繋がっていると思います。一概に有料にする、無料にするという話だけではなく、純粋にツールを便利にし続けるのも重要と思います。

プロダクトアウトなサービス開発が大変なポイント

ここまでうまくいっている話ばかり書いてきたので、大変なポイントも最後にちょっとだけ書きます。

テストメーカーはもともと、私が学生のときにマウスで選択したところが穴埋めになるツールがあったら面白いなと思って当時Visual C++でWindowsソフトウェアとして作ったものを、7年越しにWebでリプレイスしたサービスなのですが、そういう観点ではマーケットインではなくめちゃめちゃプロダクトアウトなサービスです。

そのため、「技術的に珍しいことをやっていると、無理だと確定している仕様が生まれやすい」という難しさがあります。
テストメーカーのコアであるマウスで選択した部分が穴埋めになるロジックですが、個人的にはこれはDBへの永続化や回答側の機能まで込みで考えるとそれなりに珍しい技術だと思っています(この記事を読んでいる読者のエンジニアの方で実装方法のアタリがついた方、よかったら連絡ください。喋りましょう笑)。それゆえに、機能追加にちょっとした制約がついてきています。

特に小規模のサービスだと、普通は多少の技術的負債があってもあとから時間さえかければ取り返せることが大半かと思うのですが、テストメーカーのようなツールの難しいところとして、コアロジックを組んだときに想定していなかった仕様は、あとから原理的に実装不可能になりがちというのがあります。この手のプロダクトアウトなツールを仮に事業として運営する場合、相当先まで想定しつつ、技術的にも拡張性を担保した状態で初期設計を行わないといけなくて大変だなと思いました。
要するにNotionみたいに技術的に尖ったツールを提供しながらも、いつまでも機能追加し続けられているツールは凄すぎます、という話です笑。

とはいえ今の拡張性のまま組める範囲でできることはまだまだあるので、ぼちぼちやっていきたいなと思っています。


以上でテストメーカーを支える技術のプロダクトマネジメント編を終わります。

まとめ

いろいろと書いてきましたが、個人開発を支える技術選定や開発を進めるプロダクトマネジメントの話が、個人開発にこれから取り組もうとする方や、すでに悩みながら取り組んでいる方になにか参考になれば嬉しく思います。

特に言いたいことは限りなく時間を使わずに開発できるように仕様面と技術面の両方から全力で工夫するのが大事ということです。これができるのが個人で開発する一番の利点かもしれないとすら思います。工夫して個人開発していきましょう!


もしよかったらTwitterのフォローもよろしくお願いします!同じく個人開発している方とか、採用している技術について雑談したいという方いらっしゃいましたらお気軽にDMください!

▼開発者(私)のTwitter
https://twitter.com/Meijin_garden


明日の個人開発Advent Calendarは@nabettuさんの「これで俺もAIエンジニアや!」です。よろしくお願いします!

▼個人開発Advent Calendar2022
https://qiita.com/advent-calendar/2022/individual-developers


最後まで読んでいただきありがとうございました!記事が参考になったらテストメーカーのサーバー代(という名のバッジ)を恵んでください!

Discussion