開発ブログ

BLOG

Better Stack でステータスページを付け、アプリのお問い合わせへつないだ

status.metronome.fm を Better Stack で公開した。監視の設定、Cloudflare の CNAME だけで済んだ独自ドメイン、ステータスページからアプリのお問い合わせを開く仕組みを書く。

公開 2026年10月7日

Metronome.fm に、サービスが動いているかを確かめられるステータスページ(status.metronome.fm)を付けました。使ったのは Better Stack です。Issue を立ててから公開までは同じ日のうちに終わりました。アプリ側の変更は、お問い合わせのフォームを開く部品と、ドキュメントからのリンクだけです。

この記事では、何を監視しているか、独自ドメインをどう向けたか、ステータスページからアプリのお問い合わせへどうつないだかを書きます。

Better Stack は無料のプラン(Free)のまま使っていて、ここに書く監視・独自ドメイン・日本語の版はどれも無料の範囲で動いています。

Better Stack の請求の画面。番号 1 は You're currently on the Free plan. の行
請求の画面
  1. 無料のプラン(Free)のまま使っている

ほかのサービスのステータスページを見て、Metronome.fm にもほしくなったのがきっかけです。エラーのログの送り先にすでに Better Stack を使っていたので、監視とステータスページも同じところにまとめました。

監視しているもの

Better Stack の監視(Uptime の Monitor)は 2 つあります。どちらも URL に GET を送り、返ってきた HTTP のステータスで動いているかを判定する種類です。

監視する URL間隔タイムアウト確認する地域
https://metronome.fm/app3 分30 秒ヨーロッパ・アメリカ・アジア・オーストラリア
https://metronome.fm/ja3 分30 秒同じ

/app はアプリ本体、/ja は日本語の LP です。どちらもリダイレクトを追い、SSL の証明書も確かめる設定にしています。

監視の設定の画面では、何が起きたら知らせるか(Alert us when)と、監視する URL を決めます。無料のプランで選べる条件は、URL に届かなくなったとき・キーワードを含む/含まないとき・決めたステータス以外が返ったとき・ping に応えないときで、TCP・DNS・Playwright のシナリオなどは有料です。

Better Stack の監視の設定。番号 1 は Alert us when の URL becomes unavailable、番号 2 は URL to monitor の https://metronome.fm/app
監視の設定
  1. URL に届かなくなったら知らせる(URL becomes unavailable)
  2. 監視する URL

確認は 3 分ごとで、失敗を見つけたらすぐに障害として扱い(Confirmation period を Immediate start)、3 分続けて動いていれば解決とみなします(Recovery period)。

監視の詳細設定。番号 1 は Check frequency の 3 minutes、番号 2 は Confirmation period の Immediate start
確認の間隔と、障害として扱うまでの待ち時間
  1. 3 分ごとに確認する
  2. 失敗を見つけたら、待たずに障害として扱う

SSL の証明書の期限切れやドメインの期限切れを前もって知らせる機能は、無料のプランでは使えません。

ステータスページには、この 2 つをどちらも載せています。アプリ本体と LP のどちらが落ちても、利用者から見えます。

ステータスページのサービスごとの状態。番号 1 は metronome.fm/app の行、番号 2 は metronome.fm/ja の行で、どちらも 90 日分の稼働の帯がある
ステータスページのサービスごとの状態
  1. アプリ本体(/app)
  2. 日本語の LP(/ja)

status.metronome.fm を向ける

Issue を立てたときは「Next.js で status.metronome.fm のようなサブドメインを作れるのか」が気になっていました。実際には、Next.js にもアプリのコードにも手を入れていません。ステータスページは Better Stack が配信していて、こちらは DNS で名前を向けるだけです。

metronome.fm の DNS は Cloudflare で管理しています。status に CNAME を 1 つ足し、Better Stack のステータスページの配信先に向けました。

$ dig +short status.metronome.fm CNAME
statuspage.betteruptime.com.

dig で CNAME の先がそのまま見えるので、Cloudflare のプロキシは通していません(DNS だけの設定です)。

Better Stack のステータスページの設定には向ける先の CNAME がそのまま表で出ていて、正しく向くと「The CNAME is configured correctly」と表示されます。DNS が Cloudflare なら、この画面から Cloudflare にサインインして CNAME を足すこともできます。

ステータスページの Custom domain の設定。番号 1 は CNAME の status.metronome.fm から statuspage.betteruptime.com への行、番号 2 は The CNAME is configured correctly の表示
独自ドメインの設定
  1. この CNAME を DNS(Cloudflare)に足す
  2. 正しく向くと、確認済みと表示される

今回はこのボタンから足しました。Cloudflare にサインインして許可すると、CNAME が足されます。

お問い合わせのボタンからアプリのフォームを開く

Better Stack のステータスページには、右上にお問い合わせのボタンを置けます。押したときに開く URL は設定の「Get in touch URL」で 1 つ指定し、空にするとボタンは出ません。mailto: も使えます。

ステータスページの右上。番号 1 はお問い合わせのボタン
ステータスページの右上
  1. お問い合わせのボタン。押すとアプリのフォームが開く

Metronome.fm のお問い合わせは、アプリの中のフォーム(モーダル)で受け付けています。ページとしての URL はないので、/app に ?contact=open を付けたらフォームを開くようにしました。ステータスページの設定には https://metronome.fm/app?contact=open を入れています。

ステータスページの設定。番号 1 は Get in touch URL の https://metronome.fm/app?contact=open
ステータスページの設定
  1. お問い合わせのボタンの行き先(Get in touch URL)
export const ContactLinkOpener = () => {
  const searchParams = useSearchParams();
  const router = useRouter();
  const pathname = usePathname();
  const openContactFormModal = useModalState(
    (state) => state.openContactFormModal,
  );
  const shouldOpen = searchParams.get("contact") === "open";

  const open = useEffectEvent(() => {
    const rest = new URLSearchParams(searchParams);
    rest.delete("contact");
    const query = rest.toString();
    router.replace(query ? `${pathname}?${query}` : pathname);
    openContactFormModal();
  });

  useEffect(() => {
    if (shouldOpen) open();
  }, [shouldOpen]);

  return null;
};

フォームを開いたら、URL から contact=open を消します。消さないと、ページを読み直したときや、フォームを閉じてから画面の中を移ったときに、またフォームが開いてしまうからです。ほかのクエリは残します。

Metronome.fm のアプリの上に、お問い合わせのフォームが開いている
/app?contact=open で開いた直後。アプリの上にフォームが開く

この部品はヘッダーに置いています。Next.js では、useSearchParams を使う部品があると、いちばん近い Suspense までがブラウザ側で描かれます。ヘッダー全体がそうならないよう、この部品だけを Suspense で囲みました。

日本語の版と、サイトからのリンク

ステータスページは英語の版を /、日本語の版を /ja で出しています。下端の言語の切り替えでも移れます。

翻訳を使うには、ステータスページのデザインを新しい方(Modern look)にしておく必要があります。

ステータスページの設定。番号 1 は翻訳などは Modern look で使えるという説明文、番号 2 は Status page design の Modern look
ステータスページのデザインの設定
  1. 翻訳などは新しいデザイン(Modern look)の機能
  2. デザインを Modern look にする

Better Stack には用意された翻訳(Ready-made language)がありますが、選べるのは英語・ドイツ語・フランス語・スペイン語・オランダ語・チェコ語・スウェーデン語・トルコ語で、日本語はありません。そのため、言語コードを ja にした翻訳を作り、ナビゲーション・状態の表示・障害の自動の報告など 256 か所の文言を日本語で入れました。訳は Claude に書いてもらいました。会社名は %{company_name} のような差し込みで書けます。

翻訳の設定。番号 1 は Locale の ja、番号 2 は Ready-made language の None、番号 3 は Status の欄の「ステータス」
日本語の翻訳の設定
  1. 言語コードは ja
  2. 用意された翻訳に日本語はないので None
  3. 文言を 1 つずつ日本語で入れる
ステータスページの下端。番号 1 は言語の切り替え
ステータスページの下端
  1. 言語の切り替え

Metronome.fm の側からは、ドキュメントのトップと、リリース情報の v2.5 のページからリンクしています。リンク先は表示している言語に合わせて、英語なら /、日本語なら /ja にしています。

export const getStatusPageUrl = (locale: string) =>
  locale === DEFAULT_LOCALE
    ? `${STATUS_PAGE_URL}/`
    : `${STATUS_PAGE_URL}/${locale}`;