RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-03-30中級

Rork × Trigger.dev でモバイルアプリのバックグラウンドジョブを自動化する方法

Rork で開発したモバイルアプリに Trigger.dev を組み合わせ、プッシュ通知・データ同期・コンテンツ更新などのバックグラウンドジョブを自動化する実践的な実装ガイドです。

Trigger.devバックグラウンドジョブ自動化12Rork515Supabase33プッシュ通知19

取り組みの背景 — なぜモバイルアプリにバックグラウンドジョブが必要なのか

モバイルアプリを開発していると、ユーザーがアプリを操作していない時間帯にもサーバー側で処理を実行したい場面に遭遇します。定期的なデータ同期、スケジュールされたプッシュ通知の配信、外部APIからのコンテンツ自動更新など、こうしたバックグラウンドジョブはアプリの価値を大きく高める要素です。

Trigger.dev は、TypeScript で書けるオープンソースのバックグラウンドジョブプラットフォームです。Cron スケジューリング、Webhook トリガー、リトライ機構が標準で備わっており、Rork で作ったモバイルアプリのバックエンド処理を効率的に自動化できます。

ここではRork アプリと Trigger.dev を組み合わせて、実用的なバックグラウンドジョブを構築する方法をステップバイステップで解説します。

Trigger.dev の基本概念と Rork との相性

Trigger.dev は Node.js / TypeScript ベースのジョブスケジューラで、以下のような特徴を持っています。

  • Cron ジョブ: 「毎朝9時」「1時間ごと」など時間指定で自動実行
  • イベント駆動: Webhook や API 呼び出しをトリガーに実行
  • リトライ: 失敗時の自動再試行(回数・間隔をカスタマイズ可能)
  • ダッシュボード: 実行履歴やエラーログをWebUIで確認

Rork で開発したアプリは React Native + Expo ベースで動作し、バックエンドには Supabase や Firebase を利用するケースが一般的です。Trigger.dev はこれらのバックエンドサービスと連携しやすく、アプリ側のコードを変更せずにサーバーサイドの自動化処理を追加できる点が魅力です。

環境構築 — Trigger.dev プロジェクトのセットアップ

まず、Trigger.dev のプロジェクトを作成します。Rork アプリ本体とは別のリポジトリで管理するのがおすすめです。

# Trigger.dev CLIのインストール
npm install -g @trigger.dev/cli
 
# プロジェクトの初期化
mkdir my-rork-app-jobs && cd my-rork-app-jobs
npx trigger.dev@latest init
 
# 依存パッケージのインストール
npm install @trigger.dev/sdk @supabase/supabase-js

初期化が完了すると、trigger.config.tssrc/trigger/ ディレクトリが生成されます。ジョブの定義はすべて src/trigger/ 配下に配置します。

プロジェクト構成

my-rork-app-jobs/
├── trigger.config.ts       # Trigger.dev設定
├── src/
│   └── trigger/
│       ├── scheduled/      # Cronジョブ
│       │   ├── daily-digest.ts
│       │   └── content-sync.ts
│       ├── events/         # イベント駆動ジョブ
│       │   ├── user-signup.ts
│       │   └── purchase-complete.ts
│       └── utils/
│           ├── supabase.ts # Supabaseクライアント
│           └── push.ts     # プッシュ通知ヘルパー
├── package.json
└── .env                    # 環境変数(APIキー等)

実践1 — コンテンツ自動更新ジョブの実装

ニュースアプリやキュレーションアプリでは、外部APIから定期的にコンテンツを取得してデータベースに保存する処理が必要です。以下は、1時間ごとに外部APIからデータを取得し、Supabase に保存するジョブの実装例です。

// src/trigger/scheduled/content-sync.ts
import { schedules } from "@trigger.dev/sdk/v3";
import { createClient } from "@supabase/supabase-js";
 
// Supabaseクライアントの初期化
const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
);
 
// 1時間ごとにコンテンツを同期するジョブ
export const contentSyncJob = schedules.task({
  id: "content-sync",
  // 毎時0分に実行
  cron: "0 * * * *",
  run: async () => {
    console.log("コンテンツ同期を開始します...");
 
    // 外部APIからデータを取得
    const response = await fetch("https://api.example.com/articles", {
      headers: {
        Authorization: `Bearer ${process.env.CONTENT_API_KEY}`,
      },
    });
    const articles = await response.json();
 
    // Supabaseにupsert(存在すれば更新、なければ挿入)
    const { data, error } = await supabase
      .from("articles")
      .upsert(
        articles.map((article: any) => ({
          external_id: article.id,
          title: article.title,
          body: article.body,
          thumbnail_url: article.image,
          published_at: article.publishedAt,
          updated_at: new Date().toISOString(),
        })),
        { onConflict: "external_id" }
      );
 
    if (error) {
      // エラー時はTrigger.devが自動リトライ
      throw new Error(`Supabase upsert failed: ${error.message}`);
    }
 
    return {
      syncedCount: articles.length,
      timestamp: new Date().toISOString(),
    };
    // 期待する出力例:
    // { syncedCount: 25, timestamp: "2026-03-30T05:00:00.000Z" }
  },
});

このジョブが動作すると、アプリ側では Supabase のリアルタイムサブスクリプションを通じて、新しいコンテンツが自動的に画面に反映されます。

実践2 — スケジュール通知の自動配信

ユーザーごとにパーソナライズされたプッシュ通知を、毎朝決まった時刻に自動配信するジョブを構築します。

// src/trigger/scheduled/daily-digest.ts
import { schedules } from "@trigger.dev/sdk/v3";
import { createClient } from "@supabase/supabase-js";
 
const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
);
 
export const dailyDigestJob = schedules.task({
  id: "daily-digest-notification",
  // 毎朝9時(JST)に実行 = UTC 0時
  cron: "0 0 * * *",
  run: async () => {
    // 通知を有効にしているユーザーを取得
    const { data: users } = await supabase
      .from("user_preferences")
      .select("user_id, push_token, preferred_categories")
      .eq("daily_digest_enabled", true)
      .not("push_token", "is", null);
 
    if (!users || users.length === 0) {
      return { sent: 0, message: "対象ユーザーなし" };
    }
 
    // 過去24時間の人気記事を取得
    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
 
    const { data: trending } = await supabase
      .from("articles")
      .select("id, title, category")
      .gte("published_at", yesterday.toISOString())
      .order("view_count", { ascending: false })
      .limit(3);
 
    // Expo Push APIで一括送信
    const messages = users.map((user: any) => ({
      to: user.push_token,
      title: "今日のおすすめ記事",
      body: trending?.[0]?.title || "新しい記事が公開されました",
      data: { articleId: trending?.[0]?.id },
    }));
 
    const pushResponse = await fetch(
      "https://exp.host/--/api/v2/push/send",
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(messages),
      }
    );
 
    return {
      sent: messages.length,
      timestamp: new Date().toISOString(),
    };
    // 期待する出力例:
    // { sent: 142, timestamp: "2026-03-30T00:00:00.000Z" }
  },
});

Rork アプリ側では expo-notifications でプッシュトークンを取得し、Supabase の user_preferences テーブルに保存しておくだけで、あとは Trigger.dev が自動的に通知を配信してくれます。プッシュ通知の高度なセグメンテーションや A/B テストについては、Rork アプリのプッシュ通知マスタープラン でさらに詳しく解説しています。

実践3 — イベント駆動ジョブ(ユーザーアクション起点)

Cron ジョブだけでなく、ユーザーのアクション(会員登録、購入完了など)をトリガーにジョブを実行することもできます。

// src/trigger/events/user-signup.ts
import { task } from "@trigger.dev/sdk/v3";
import { createClient } from "@supabase/supabase-js";
 
const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
);
 
// ユーザー登録時のウェルカムシーケンス
export const userSignupJob = task({
  id: "user-signup-welcome",
  // 最大3回リトライ、間隔は指数関数的に増加
  retry: {
    maxAttempts: 3,
    factor: 2,
    minTimeoutInMs: 1000,
    maxTimeoutInMs: 30000,
  },
  run: async (payload: { userId: string; email: string }) => {
    // 1. ウェルカムメール送信
    await sendWelcomeEmail(payload.email);
 
    // 2. 初期おすすめコンテンツの生成
    const { data: popular } = await supabase
      .from("articles")
      .select("id")
      .order("view_count", { ascending: false })
      .limit(5);
 
    await supabase.from("user_recommendations").insert(
      (popular || []).map((article: any) => ({
        user_id: payload.userId,
        article_id: article.id,
        reason: "popular",
      }))
    );
 
    // 3. 分析イベントの記録
    await supabase.from("analytics_events").insert({
      event_type: "user_onboarded",
      user_id: payload.userId,
      metadata: { source: "trigger.dev" },
    });
 
    return { success: true, userId: payload.userId };
  },
});
 
async function sendWelcomeEmail(email: string) {
  // メール送信ロジック(Resend, SendGrid等)
  console.log(`ウェルカムメール送信: ${email}`);
}

Rork アプリからこのジョブをトリガーするには、Supabase Edge Functions 経由で Trigger.dev の API を呼び出します。

// Supabase Edge Function: functions/on-signup/index.ts
import { tasks } from "@trigger.dev/sdk/v3";
 
Deno.serve(async (req) => {
  const { userId, email } = await req.json();
 
  // Trigger.dev ジョブをキック
  await tasks.trigger("user-signup-welcome", {
    userId,
    email,
  });
 
  return new Response(JSON.stringify({ ok: true }), {
    headers: { "Content-Type": "application/json" },
  });
});

デプロイとモニタリング

Trigger.dev のデプロイは非常にシンプルです。

# 本番環境へデプロイ
npx trigger.dev@latest deploy
 
# ローカルでの開発・テスト
npx trigger.dev@latest dev

デプロイ後は Trigger.dev のダッシュボード(https://cloud.trigger.dev)からジョブの実行状況をリアルタイムで確認できます。

  • 実行履歴: 各ジョブの成功/失敗、実行時間、出力を確認
  • リトライ状況: 失敗したジョブの自動リトライ回数と結果
  • アラート: Slack や Discord への失敗通知を設定可能

アプリの運用を自動化し、障害時にも迅速に気づける体制を整えたい方には、モバイルアプリの自律運用アーキテクチャ の記事もおすすめです。

よくあるエラーと対処法

タイムアウトエラー

Trigger.dev のデフォルトタイムアウトは 60 秒です。外部API呼び出しが遅い場合は maxDuration を設定しましょう。

export const longRunningJob = schedules.task({
  id: "long-running-sync",
  cron: "0 3 * * *",
  // タイムアウトを5分に延長
  maxDuration: 300,
  run: async () => {
    // 時間のかかる処理
  },
});

環境変数の未設定

Trigger.dev ダッシュボードの「Environment Variables」から、SUPABASE_URLSUPABASE_SERVICE_KEY などの環境変数を設定してください。.env ファイルはローカル開発用であり、本番環境には反映されません。

リトライが多発する場合

外部APIのレートリミットに引っかかっている可能性があります。retryfactor を大きくして間隔を広げるか、バッチサイズを小さくして対応します。

まとめ

Trigger.dev を活用することで、Rork で開発したモバイルアプリに強力なバックグラウンドジョブ機能を追加できます。コンテンツの自動更新、パーソナライズ通知の配信、ユーザーアクション起点の自動処理など、アプリの価値を高める自動化をサーバーサイドで実現できるのが最大のメリットです。

TypeScript で書けるため、React Native / Expo を使った Rork アプリの開発者にとって学習コストが低く、ダッシュボードによるモニタリングも充実しています。まずは無料プランで小さなジョブから始めて、アプリの運用効率を体験してみてください。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-07-03
App Store Connect API の日次集計が月末に合わなくなるとき — JWT 失効・レポート確定遅延・突合の運用メモ
App Store Connect API で自動化した売上・レビュー収集は、止まらずに「欠け」ます。401/404/429 が生む3種類の静かな欠損を fetch ログと突合クエリで検出し、バックフィルで埋める運用設計を実装コード付きでまとめます。
開発ツール2026-03-29
Rork アプリのプッシュ通知マスタープラン — セグメント配信・A/Bテスト・自動化パイプラインの実装ガイド
Rork アプリにおけるプッシュ通知の上級実装ガイド。ユーザーセグメント配信、A/Bテスト、自動化パイプライン、リテンション向上戦略まで体系的に解説します。
開発ツール2026-07-17
許可を聞かずに通知を届ける — Rork アプリの provisional 認可と、Expo の定番コードが握りつぶすもの
iOS には許可ダイアログを出さずに通知を配り始める provisional 認可があります。ところが Expo 公式が載せている定番の登録コードをそのまま使うと、provisional で通った端末が「拒否」として扱われ、避けたかったはずのダイアログが出ます。granted が false になる仕組みから、5値で許可状態を扱うフック、静かな配信を前提にした通知設計、昇格を求める判断、計測の分離までを実装込みで整理しました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →