PubliraGitHub

読者、編集者、オペレーターのためのアプリ

Next.jsで作った3つのWebアプリとFlutterアプリ、それらが送るメールです。どれも対象とする利用者が異なります。

読者向けサイト

apps/web-storefront

読者が訪れるサイトで、出版社自身のブランドで公開されます。作品の閲覧や検索、ランキング、フォロー、サインイン、ページをめくって読むビューアーを備えています。

カタログ出版社が特集する作品の下に、今週のランキング、新着エピソード、曜日ごとの更新、おすすめのレーベルや著者を紹介するコーナーが並びます。コンソールで固定したお知らせは、読者が閉じるまですべてのページの上部に表示されます。どの画面もPubliraではなく出版社のブランドで表示されます。
ジャンル各ジャンルは、そのジャンルで上位の作品の表紙か、編集者がアップロードしたアートワークで表示され、作品数が添えられます。ジャンルを開くと、今週よく読まれている作品の下にそのジャンルの全作品が並び、作品一覧と同じように並べ替えや絞り込みができます。ジャンルは固定のリストではなく、テナントが独自に設定する分類です。
ランキングデイリーとウィークリーのランキングで、各行には前回からの順位の変動が表示されます。順位は手作業で並べたものではなく、エピソードを開いたりリアクションしたりといった読者の行動をバッチ処理で集計したものです。R15とR18の作品は専用のランキングに分かれ、閲覧できる読者だけが開けます。
シリーズ一覧公開中のすべてのシリーズを、ジャンルや連載状況で並べ替えたり絞り込んだりでき、無料エピソードのある作品だけに絞ることもできます。年齢制限のある作品はどの一覧でもマークが付き、読者が閲覧できることを確認するまで伏せて表示されます。
シリーズ詳細表紙、あらすじ、レーベル、ジャンル、タグに加えて、原作や作画といった役割とともにすべての著者が表示され、フォローと共有のボタンがあります。その下にはエピソードが読む順に並び、無料か有料かが示されるので、サインインする前から今すぐ読めるエピソードがわかります。
エピソードビューアーページはcanvasに描画され、編集者が設定した見開きの開始ページから、右から左へ見開き単位でめくります。ツールバーのスライダーも見開き単位で移動し、最後のページを過ぎると読者はエピソードにリアクションでき、次のエピソードに進めます。ビューアーはnpmで公開しているパッケージそのものなので、ページ送りや見開き、読む方向はライブラリの機能です。
検索ひとつのキーワードに一致するシリーズ、著者、レーベルをまとめて表示し、グループごとに一覧を開けます。検索できるのはテナントが公開したものだけなので、編集中の作品が見つかることはありません。
著者一覧テナントで公開している著者と、それぞれの作品数の一覧です。著者のページには画像とプロフィール、フォローのボタン、その著者がクレジットされたすべての作品が並びます。著者は管理コンソールで管理するプロフィールなので、同じ著者はどの作品でも同じプロフィールとして表示されます。
サインインサインインでも会員登録でも、メールアドレスとパスワードか、読者がすでに持っているAppleやGoogleのアカウントを使えます。パスキーを登録した読者はパスキーでもサインインできます。これらのサービスはテナントごとに設定するもので、コンソールに認証情報を登録すると表示されます。テナントが利用規約を指定していれば読者は同意を求められ、規約が改訂されたときにも改めて同意を求められます。
読者自身のページフォローしている作品や著者の新着、購入したエピソードとそれぞれを読める期間、新しいエピソードの通知をメールで受け取るかブラウザの通知で受け取るかの設定です。

管理コンソール

apps/web-admin

編集者が作業するコンソールです。カタログと公開キュー、決済とサインインのサービス、公開サイトのテーマとページ、読者からのメッセージ、読者の購入と返金、著者への支払額を扱い、これらへの変更はすべて記録されます。

ダッシュボード公開中の作品、下書きのエピソード、公開予定の件数の下に、対応が必要なものをまとめたキューがあります。キューには下書きと公開予定のものが公開日時とともに並ぶので、編集者はコンソールを開くだけで対応が必要なものを確認できます。
シリーズタイトル、レーベル、公開日、閲覧期間、年齢レーティング、状態をひとつの表で一覧でき、連載状況やレーティングで絞り込めます。作品を開くと詳細画面になり、タイトルとあらすじをテナントが提供する言語ごとに入力できます。著者ごとに担当する役割と売上の配分率を設定してクレジットでき、配分率を入力するとその場で出版社の取り分が計算されます。作品に設定したクレジットは、新しく作るエピソードの初期値として使われます。
エピソード作品のエピソードを読む順に並べ、番号を振り直すのではなくドラッグで (矢印キーでも) 並べ替えます。公開日時はテナントのタイムゾーンで予約でき、ページは画像、ZIP、EPUBのいずれかでアップロードして同じように並べ替えられます。公開後でもページごとに差し替えや削除ができます。
著者テナントが著者のクレジットに使う役割は、名前を変えたり、クレジットの表示順に並べ替えたりできます。著者のページでは、テナント管理者がその著者本人の読者アカウントを紐づけられます。紐づけた著者は自分のエピソードを購入せずに読めますが、評価することはできません。
決済このテナントがWebの決済に使うサービス (StripeかPAY.JP) とその鍵、アプリで販売するためのApp StoreとGoogle Playの認証情報です。シークレットは書き込み専用で、あとから開いても設定状態とマスクされた表示が見えるだけで、値そのものは表示されません。
サインインとアプリのリンクこのテナントの読者がサインインに使えるAppleとGoogleのアカウントと、テナントのリンクを開くAndroidとiOSのアプリの設定です。どちらもテナントごとに設定するので、同じ環境で運営する出版社はそれぞれ自社の名前で読者をサインインさせ、リンクを自社のアプリで開けます。
テーマブランドカラーとその上に載る文字の色、読者が最初に目にする書体を、公開サイトに表示するロゴやアイコンと並べて設定し、公開サイトと同じ部品で組み立てたプレビューで確認できます。プレビューは編集のたびに更新されますが、公開サイトの見た目はテーマを保存するまで変わりません。
ページとお知らせテナント独自のページはMarkdownで書き、言語ごとに翻訳を用意できます。公開した版はすべて残るので、比較したり以前の版に戻したりできます。お知らせはサイトを訪れるすべての人に表示され、そのうちひとつをすべてのページ上部のバナーとして固定できます。
お問い合わせ読者がサイトの問い合わせフォームから送ったメッセージを、返信先のアドレス、担当のスタッフ、対応状況とともに一覧にします。メッセージのページで書いた回答は読者にメールで送られ、メッセージの下に残ります。新しいメッセージはスタッフにもメールで通知されるので、コンソールを開いたままにしておく必要はありません。
レポートと著者への支払いエピソードごとに最後まで読んだ会員の数と、ひと月の売上、返金、著者それぞれへの支払額を確認できます。月の区切りはテナントのタイムゾーンで決まります。月を締めるとその後の売上に左右されない明細になり、CSVでダウンロードできます。締めたあとに記録された返金は、調整額として次の明細に繰り越されます。
監査ログ誰がいつ何をしてどうなったかを、実行者と対象のレコードとともに表示します。期間や操作、実行者で絞り込め、日付はサーバーではなくテナントのタイムゾーンの暦日として扱われます。

プラットフォームコンソール

apps/web-platform

プラットフォーム全体を運用するオペレーター向けのコンソールです。環境にまだ必要な設定、テナントの状態、テナントをまたぐイベント、全テナントの読者を管理し、オブジェクトストレージからセキュリティポリシーまで全テナント共通の設定もここで行います。

ダッシュボード環境にまだ必要な設定と各設定画面へのリンクの下に、テナント数と、テナントの作成やロールの付与、アカウントの追加といったテナントをまたぐ最近のイベントが並びます。オペレーターはコンソールを開くとまず、環境の準備が整っているかを確認できます。
テナント登録されたすべてのテナントを状態と作成日とともに一覧にし、名前かIDで検索できます。テナントを開くとプロフィール、ドメイン、メンバーが表示されます。このコンソールが扱うのはテナントの状態と管理者だけで、カタログには関わりません。カタログは各テナントが自分のコンソールで管理します。
ユーザー全テナントの読者をひとつの一覧にまとめ、所属テナント、登録日、状態を表示します。オペレーターはここでアカウントを停止したり削除したりできますが、読者がどの作品を読めるかは、その作品を公開したテナントが決めます。
環境の設定全テナントのアップロード先となるS3互換のバケット (環境でひとつ)、メール送信に使うSMTPリレー、サインインとメール送信を保護するレート制限、Web Pushの署名に使う鍵ペアを設定します。保存した変更は、再起動しなくても稼働中のすべてのサーバーに反映されます。

モバイルアプリ

mobile

同じカタログをスマートフォンで読めるアプリです。AndroidとiOSをひとつのFlutterコードベースでまかない、テナントの名前とテーマで表示されます。サイトを経由せずに公開APIを直接呼び出し、メールアドレス、パスキー、Apple、Googleでサインインでき、エピソードはストアかサイトの決済で購入できます。読者が開いたエピソードや保存したエピソードは端末に保持されます。

カタログアプリバーにはテナントの名前とテーマが反映され、コンソールで固定したお知らせと読みかけのエピソードの下に、ジャンルと今週のランキングが続きます。画面下部のバーからは、ビューアー以外のどの画面からでもホーム、検索、ライブラリ、通知、アカウントに移動できます。
ジャンルと検索ジャンルは表紙を使ったタイルで表示され、開くとサイトと同じ並べ替えと絞り込みで作品を一覧できます。検索では、ひとつのキーワードに一致する作品、著者、レーベルが表示されます。すべての一覧はWebサイトと共通の公開APIから取得するので、見つかるのはテナントが公開したものだけです。
作品と著者表紙、テナントが定めた役割でのクレジット、レーベル、ジャンル、タグに加えて、作品と著者それぞれのフォローボタンと、サイトのリンクを共有するボタンがあります。著者のページにも同じフォローボタンがあり、フォローしている作品や著者の新しいエピソードはプッシュ通知で届いて、タップするとそのままビューアーで開きます。
エピソードビューアーサイトと同じエピソードを、編集者が設定した見開きと読む方向でレイアウトし、スライダーでページを移動できます。有料のエピソードは、テナントの設定に応じてストアの購入画面かサイトの決済で購入します。ページのスクリーンショットを撮ると、ページの利用についてのテナントの注意書きが表示されます。
ライブラリと受信箱読みかけ、フォロー、端末に保存したエピソード、おすすめをそれぞれ一覧で確認でき、購入したエピソードとそれぞれを読める期間、読者に届いた通知の受信箱もあります。保存したページは端末上で生成した暗号鍵で暗号化して保存し、オフラインで読んだ記録はネットワークに再接続したときに送信します。
アカウントアイコン、名前、アドレス、パスワード、紐づけたAppleとGoogleのアカウント、メール通知、テナントのページ、テナントへの問い合わせ、アカウントの削除まで、読者はアプリを離れずに済ませられます。サインインでは、メールアドレスに加えてAndroidではGoogle、iOSではAppleを選べます。

送られるメール

apps/email-renderer

アカウント関連のメールとスタッフへの通知です。専用のレンダラーがReactコンポーネントからHTMLを生成し、プレーンテキストのパートと一緒に送ります。テナントの読者やスタッフに届くメールにはPubliraではなくテナントの名前が入り、テナントの言語で書かれます。日本語、韓国語、中国語で英数字と隣り合う部分のスペースは、サイトと同じくメールクライアントの描画に任せています。

アドレスの確認新しい読者が最初に受け取るメールです。アドレスを確認するボタン、リンクの有効期限、ボタンを表示できないメールクライアント向けのリンクが記載されています。
パスワードの再設定新しいパスワードを設定するためのリンクで、送信から1日で有効期限が切れます。テナントのほかのメールと同じレイアウトです。
スタッフへのメッセージ読者が問い合わせフォームから送った内容に、返信先のアドレスとサインインしていたアカウントが添えられるので、スタッフはコンソールのメッセージのページからでも、自分のメールクライアントからでも回答できます。