Educational Products: Month 1

Michael Lynch

教育プロダクト:1ヶ月目

一言まとめ

ブログ講座を再開します。

ハイライト

  • 2020年に作ったブログ講座を再始動しました。
  • htmxはなかなか良いのですが、期待していたすべてを叶えてくれるわけではありませんでした。
  • 昔運営していたケトジェニック食品サイト「Is It Ketoの買い手を探しています」。

「Hit the Front Page」の再始動

2020年に、「Hit the Front Page of Hacker News」というブログについての動画講座を作りました。内容には自信があり、受講生からも良いフィードバックをいただきましたが、十分に力を注げなかったという思いが残っていました。

コースを公開した当時、TinyPilotが急成長していたため、講座の宣伝や教材の改善に時間を割くことができませんでした。

前回のブログ記事で、読者の皆さんに次に何をやってほしいかアンケートを取ってみました。何かを教えてほしいと答えてくれた方に絞った結果がこちらです。

次に教えてほしい内容への関心を示す積み上げ棒グラフ。「開発者の文章力向上を支援する」が「ソフトウェア開発への意図的練習の応用」とともに32票で同率1位。「開発者向けのブログ運営」は31票で3位。

前回のブログ記事で行った読者アンケートの結果

データの解釈はいろいろ考えられますが、私が受け取った印象は、文章術を教えてほしいという声が特に強いということでした。意外だったのは、「意図的練習をソフトウェア開発に応用する方法」も上位に入っていたことです。熱量はやや控えめでしたが、関心の高さがうかがえました。

既存の講座はすでにほぼ完成しており、数え方によっては2位か3位に入る人気があったため、ほこりを払って2024年版としてアップデートして再公開することにしました。

パイロット版の受講生を集める

Rob Fitzpatrickの著書Write Useful Booksには、教育プロダクトへの取り組み方について大きな影響を受けました。彼は、本や動画講座を出す前に必ずライブで教えるべきだと主張しています。実際の受講生からのフィードバックをもとに改善を重ねるためです。

妻と私は8月末に第一子が生まれる予定で、出産後は数ヶ月間、家族との時間のために活動を休止するつもりでした。この講座を検討していた時点で、出産予定日まであと10週間ほどしかなく、講座自体が6週間かかるため、余裕はほとんどありませんでした。

講座についての案内文を書き、ブログの読者の皆さんにメールでお知らせしました。興味がある方は簡単な応募フォームに記入してもらい、応募があった方には一人ひとりの回答に合わせた返信をし、参加を確定するための支払いリンクをお送りしました。

結果は次のとおりです。

  • 1,944人の読者に講座の案内メールが届きました。
  • 11人が興味ありとしてアンケートに回答してくれました。
  • 7人が講座を購入してくれました。
    • アンケート後に申し込みに至らなかった4人のうち、3人は開催時間の都合が合わなかったためでした。

配信プラットフォーム探し

ビデオ通話でZoomに代わる現実的な選択肢がほとんどないことに驚きました。セキュリティについて虚偽の説明をしていたことが発覚して以来、Zoomは避けてきたのですが、ライブ講座ではほぼ独占状態のようです。

ここ数年、仕事のミーティングではJitsi Meetを使ってきて、概ね満足していました。ただ、Zoomのミーティングに参加すると、やはり品質が良いと感じます。Jitsi Meetの有料プランを探してみましたが、すべて「要問い合わせ」となっており、おそらく月額1,000ドル以上はかかるでしょう。

というわけで、Jitsiは多少使いにくいものの、なんとか使えています。録画機能がないため、次のような方法で対応しています。

  1. ノートパソコンで授業のビデオ通話をホストします。
  2. デスクトップPCから同じ通話に参加します。
  3. デスクトップ側で通常の画面収録ソフトを使って通話を録画します。
  4. 動画をPicoShareにアップロードします。
  5. PicoShareのリンクを受講生にメールで送ります。

理想よりは手間がかかりますが、思わぬ利点もあります。スライドがノートパソコンの画面いっぱいに表示されていても、デスクトップのモニターで全員の顔を見られるのです。

もしJitsi Meetより良い代替手段をご存知でしたら、ぜひ教えてください

Hacker Newsから軸足を移すべきか

受講してくれた方の約半数は、Hacker News自体にはあまり興味がないと言っていました。私の文章が好きで、執筆プロセスをもっと知りたいという理由で、Hacker News色が強いにもかかわらず申し込んでくれたのです。

改めてアンケート結果を見ると、ブログそのものよりも、より広い意味での「文章を書くこと」への関心の方が高いようです。そして、Hacker Newsを具体的に求める声はありませんでした。

そこで、Hacker Newsから離れて、より一般的な内容に軸足を移すべきか悩んでいます。

Hacker Newsから離れることへの懸念は、自分の強みが薄れてしまうことです。ブログや文章術を教えている人は無数にいるので、その中では埋もれてしまう気がします。一方で、Hacker Newsに特化すれば、他に誰もやっていない分野なので、その領域では世界一の講師になれます。

もう一つの問題は、ブログでの成功実績のほとんどがHacker Newsに関わるものだということです。個人ブロガーの中では、Hacker Newsで異例の成果を出してきました。より一般的な文章講座にするとなると、胸を張れる実績は少なくなります。ブログで大きく稼いでいるわけでも、膨大な読者数を誇っているわけでもありません。

一方で、講座を購入してくれた方の多くは、まず私自身を見つけて、そこから講座にたどり着いた人たちだと思います。「Hacker Newsの世界的第一人者」を探して来たわけではないでしょう。

もしかすると、大勢の競合を気にしすぎる必要はないのかもしれません。いずれにせよ、私の講座への導線は、私自身か口コミを通じたものになるはずですから。

今回の講座はHacker Newsにフォーカスした元の形式で95%完成しているので、まずはこのまま公開します。それが終わったら、教材をより汎用的な内容にアレンジしていくつもりです。

htmxを学ぶ

ここ2年ほど、htmxという名前を目にする機会がどんどん増えてきました。友人のCory Zueがhtmxを使っていることもあり、興味を引かれていました。

長い間、一番の壁はhtmxの良さが理解できないことでした。

htmxのランディングページの冒頭には、「なぜHTTPリクエストを送れるのは<a><form>だけなのか?」と書かれています。これを読んで、「確かにそうなれば便利だけど、JavaScriptならどのHTML要素からでもあらゆるリクエストを送れるのに、数行のJavaScriptを削るためだけに新しいやり方を丸ごと導入する必要があるのか?」と感じていました。

最終的に腑に落ちるきっかけになったのは、書籍Hypermedia Systemsでした。htmxと同じ著者たちが書いた本で、htmxが生まれた動機や、具体的な活用シーンが詳しく解説されています。

もし4年前の自分にhtmxを勧めるとしたら、こんなふうに説明すると思います。

4年前の自分へのhtmxプレゼン

ウェブサイトを作り始めたばかりの頃、こんなHTMLを書いていませんでしたか?

<form action="/users" method="POST">
  <input name="first-name" placeholder="First name" />
  <input name="last-name" placeholder="Last name" />
  <input type="submit" value="Add user" />
</form>

今なら、こんな書き方はしないはずです。フォーム送信のたびにページ全体を再読み込みしたくないからです。全画面の再読み込みは遅く、ユーザーを戸惑わせます。ましてや「ユーザーを追加しました」というメッセージを出したいだけならなおさらですし、サーバー側で入力が拒否されたときに入力内容をすべて消してしまうのも避けたいところです。

そこで代わりに、JavaScriptを使ってこんなふうに書くでしょう。

document.addEventListener("DOMContentLoaded", () => {
  document.querySelector("form").addEventListener("submit", (evt) => {
    evt.preventDefault(); // Block default submit.
    fetch(`/users`, {
      method: "POST",
      credentials: "include",
      headers: {
        Accept: "application/json",
      },
      body: JSON.stringify({
        firstName: document.querySelector("[name='first-name']"),
        lastName: document.querySelector("[name='last-name']"),
      }),
    })
      .then((response) => {
        if (response.ok) {
          return response.json();
        }
        // TODO: Handle errors too.
      })
      .then((result) => {
        // TODO: Handle success.
      });
  });
});

それほど大量のJavaScriptではありませんが、フォームが必要になるたびに同じようなコードを書き直すことになります。共通化してリファクタリングすることもできますが、そうするとUIのロジックが複数のファイルに分散してしまいます。サーバーとのやり取りのたびに、余計な手間がかかるのです。

あるいはReactやVueのような重量級のフレームワークに頼る方法もありますが、そうなると自分のコードとブラウザに表示されるものとの間に、無数のJavaScriptの抽象レイヤーが挟まることになります。

htmxが約束するのは、初めてウェブページを作った頃のようなシンプルさへの回帰です。HTMLを書いたあとでロジックをすべてReactや手書きのイベントハンドラに押し付けるのではなく、htmxをアプリに組み込み、フォームをこんなふうに書けるようになります。

<form hx-post="/users" hx-target="this">
  <input name="first-name" placeholder="First name" />
  <input name="last-name" placeholder="Last name" />
  <input type="submit" value="Add user" />
</form>

あとはhtmxが面倒を見てくれるので、カスタムのJavaScriptを書かなくてもそのまま動きます。

htmxを使ってみた感想

htmxを試すために、ScreenJournalの一部をhtmxで書き直しています。ScreenJournalは私が作っているオープンソースの映画レビューアプリです。映画版のGoodreadsのようなもので、Letterboxdのオープンソースで見た目はイマイチな版、と言えばイメージしやすいかもしれません。

ScreenJournalは、映画のレビューをするための趣味で作っているウェブアプリです。

書き直しの良い例が、通知設定ページをhtmxで再実装したことです。どのメールを受け取るかをユーザーが設定できるページがあります。

ScreenJournalの通知設定ページ

通知ページでは、次のような処理のために大量のカスタムJavaScriptが必要でした。

  • ページを再読み込みせずにfetchでフォーム内容を送信する。
  • リクエスト送信中はフォームの入力を無効化する。
  • リクエスト送信中にステータススピナーを表示する。
  • リクエストが失敗したときにエラーメッセージを表示する。

そして、バニラJavaScriptからhtmxへの置き換え結果がこちらです。

全体としてコード行数が減り、特にJavaScriptの行数が大幅に減りました。ロジックがフロントエンドからバックエンドに移ったのも、私好みです。バックエンドのコードの方がUIのコードよりテストしやすいと感じているからです。

htmxを使ってみて、現時点で感じていることをまとめます。

htmxは抽象化レイヤーを追加するが、直感的です

  • VueやAngularでは、自分のコードがどうウェブアプリに変換されているのか全く見当がつきませんでした。
  • htmxでは、動きが十分に直感的なので、見た通りの挙動から自分でもhtmxを再実装できそうな気がします。

htmxのエラーハンドリングは物足りません

  • htmxのモデルでは、サーバーにリクエストを送り、そのレスポンスをページ上の単一の要素に差し込むことが前提になっています。
  • 問題は、成功時にはHTMLフォームを置き換えたいのに、エラー時にはフォームはそのまま残して、フォームの下にエラーを表示したいという点です。
  • htmxとしての回答は「サーバー側でユーザーの入力を含めてHTMLフォームを再描画すればよい」というものですが、これは既に存在するものを一から再描画することになりますし、XSS脆弱性のリスクも広がるため、あまり好きではありません。
  • 自前でイベントハンドラを書けば回避できますが、そうなるとフレームワークと戦っている感覚が出てきます。

htmxはContent Security Policy(CSP)を弱めます

  • CSPはクロスサイトスクリプティング(XSS)を防ぐ最後の砦として気に入っています。
  • htmxは概ねCSPと互換性がありますが、htmxが担う役割が大きいため、攻撃者がカスタムHTMLを書き込めるようになることは、実質的に任意のJavaScriptを書き込めるようになることと同じです。
    • <form action=/delete-account" method="post" onload="this.submit()">
      • CSPによりこのコードの実行はブロックされます。
    • <form hx-post="/delete-account" hx-trigger="load">
      • CSPはこの同等のコードの実行を許可してしまいます。
  • htmxを使っても安全なアプリケーションを作ることはできますが、XSSに対する信頼できる最後の防御線としてCSPに頼ることは難しくなります。

Is It Ketoの売却

今週気づいたのですが、いつの間にかAmazonがアフィリエイトリンクの仕様を変更したため、Is It Keto上のアフィリエイトリンクの90%が切れてしまっていました。サイト自体は今でもGoogle AdSenseで収益を上げていますが、もう保守に時間を割くことができません。

サイトを購入してくれる方を探しています。個人開発者や起業を目指す方から魅力的なオファーをいただければ、市場価格より安くお譲りするつもりです。

まとめ

今月やったこと

  • 少人数の受講生に向けてブログ講座の授業を始めました。
  • ScreenJournalの多くをhtmxに置き換えることで、htmxを学びました。
  • 講座のボーナスコンテンツの1本目を収録しました。

学んだこと

  • Hacker Newsという切り口に、自分が思っていたほど縛られる必要はないと気づきました。
    • 受講してくれる人は、Hacker Newsでの実績よりも、私の文章自体を気に入って来てくれる可能性が高いので、そうした受講者像をもっと考えるべきだと感じました。

来月の目標

  • 講座から4回分を公開できるクオリティで収録します。
  • 新バージョンの講座の販売を開始します。

協力のお願い

ビデオ通話プラットフォームについて

次の条件を満たすビデオ通話プラットフォームについて、おすすめがあればぜひ教えてください。

  • 必須:最大10名が90分間の通話に参加できること。
  • 必須:参加者が新しいアカウントを作ったり、端末にソフトをインストールしたりせずに参加できること。
  • 必須:月額80ドル以下であること。
  • あれば嬉しい:ビデオ通話を録画できること。

コースプラットフォームの経験について

MavenやUdacityのようなコースプラットフォームで、講師や受講生として経験がある方がいれば、ぜひ話を聞かせてください。

原文は Michael Lynch により に公開されました。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。