学生団体でSlackを使用しているとき、チャンネルのメンバー追加や複数人へのDM送信が面倒だな~と感じて作ったツールです。
- バックエンド: Google Apps Script
- フロントエンド: Next.js (
frontend) - フロントからGASへの接続: Next.js Route Handler (
frontend/app/api/gas/route.ts) 経由 - コンテナ: Docker / Docker Compose
- GAS APIエンドポイント:
Api.gs - Next.jsアプリ:
frontend/一式 - Docker:
docker-compose.yml,frontend/Dockerfile
以下は「初期セットアップを最初に1回行う」ための手順です。
- Google Apps Script エディタで対象プロジェクトを開く
Code.gsがあることを確認するApi.gsを追加して保存する
- 左メニューの歯車アイコン(プロジェクトの設定)を開く
- 「スクリプト プロパティ」セクションで「スクリプト プロパティを追加」を押す
- 以下のキー/値を追加して保存する
- キー:
FRONTEND_API_SHARED_SECRET - 値: 推測されにくいランダムな長い文字列
例:
FRONTEND_API_SHARED_SECRET=3x0h...十分に長いランダム値...
この値は、後でフロントエンド側(Cloudflare Pages の環境変数 / ローカルの .env)にも同じ値を設定します。
このプロジェクトで使う Script Properties は、まとめて次のとおりです。
FRONTEND_API_SHARED_SECRET: フロントエンドとGASのAPI認証に使う共有シークレット
SPREADSHEET_ID: Slack名簿や各種データを保存しているスプレッドシートIDSLACK_BOT_TOKEN: Slack API 呼び出し用の Bot TokenSLACK_CLIENT_ID: Slack OAuth の Client IDSLACK_CLIENT_SECRET: Slack OAuth の Client SecretFRONTEND_REDIRECT_URL: フロントエンドのベースURL(例:http://localhost:3333)SHAREABLE_URL: 共有リンクや送信文面で使うURL(必要な機能を使う場合のみ)
EXPORT_SHARED_FOLDER_ID: 名簿エクスポートで使う共有フォルダIDNEXT_YEAR_CONTINUE_ENABLED: 次年度継続の機能を有効化する場合にtrue
FRONTEND_API_SHARED_SECRETを決めるSPREADSHEET_IDと Slack 認証系の値を入れる- フロント連携用に
FRONTEND_REDIRECT_URLを入れる - 共有リンクや出力先フォルダを使う機能があれば
SHAREABLE_URLとEXPORT_SHARED_FOLDER_IDを入れる - 次年度継続を使うなら
NEXT_YEAR_CONTINUE_ENABLED=trueを設定する - すべての値は GAS の Script Properties に保存し、Git には含めない
例:
FRONTEND_API_SHARED_SECRET=replace-with-long-random-secret
SPREADSHEET_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SLACK_BOT_TOKEN=xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
SLACK_CLIENT_ID=1234567890.1234567890
SLACK_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
FRONTEND_REDIRECT_URL=http://localhost:3333
SHAREABLE_URL=https://example.com/share
EXPORT_SHARED_FOLDER_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxx
NEXT_YEAR_CONTINUE_ENABLED=true
- 右上の「デプロイ」→「新しいデプロイ」を選択
- 種類で「ウェブアプリ」を選択
- 実行ユーザーとアクセス権を要件に合わせて設定
- 「デプロイ」を実行
- 発行されたWebアプリURLを控える
- フロントエンドからAPIを呼び出す
- GAS側で
Unauthorized requestが出ないことを確認する - もし
Unauthorized requestが出る場合は、- GASの
FRONTEND_API_SHARED_SECRET - フロントエンドの
FRONTEND_API_SHARED_SECRETの一致を確認する
- GASの
このプロジェクトでは、通常の SpreadsheetApp や UrlFetchApp は追加設定なしで使えます。
ただし、Drive.Files を使う機能があるため、Google Apps Script の 高度な Google サービス で Drive API を有効化してください。
有効化の流れは次のとおりです。
- Apps Script エディタの左メニューで「サービス」を開く
- 一覧から「Drive API」を追加する
- 必要なら Google Cloud 側でも同じプロジェクトで Drive API を有効化する
- 保存して再デプロイする
補足:
- これは名簿エクスポートやフォルダ参照など、
Drive.Filesを使う処理で必要です SpreadsheetAppを使うだけの処理には追加サービスは不要ですPropertiesServiceも追加サービスではなく、そのまま利用できます
Slack 連携に必要なアプリ設定は、最初に 1 回だけ行います。
- Slack API の管理画面で「Create New App」を開く
- 「From scratch」を選ぶ
- App Name を入力する
- 対象の Workspace を選んで作成する
- 左メニューで「OAuth & Permissions」を開く
- 「Redirect URLs」にフロントエンドの Slack コールバックURLを追加する
- 現行実装では
getAuthUrl()のredirect_uriに/auth/slack/callbackを使用する - GAS の WebアプリURLではなく、フロントエンド側のコールバックURLを登録する
- 例(ローカル):
http://localhost:3333/auth/slack/callback - 例(本番):
https://<your-frontend-domain>/auth/slack/callback
- 現行実装では
- 「User Token Scopes」に次の権限を追加する
chat:writeusers:readusers:read.emailchannels:readgroups:readchannels:writegroups:write
- 必要に応じて「Bot Token Scopes」に次の権限も追加する
chat:writeusers:readusers:read.emailchannels:readgroups:readchannels:writegroups:write
- 「Install to Workspace」または再インストールを実行する
- 表示された
Client IDとClient Secretを控える
Slackアプリの設定値は、GAS の Script Properties に以下のように対応させます。
SLACK_CLIENT_ID: Slackアプリの Client IDSLACK_CLIENT_SECRET: Slackアプリの Client SecretSLACK_BOT_TOKEN: Slackアプリをワークスペースにインストールした後に取得できる Bot Token
- GAS の Webアプリを開く
- Slackログイン画面から認証を実行する
users.lookupByEmailやchat.postMessageが成功することを確認する- 権限不足エラーが出る場合は、Slackアプリの scopes を見直す
補足:
- このプロジェクトでは Events API や Slash Commands は使っていません
- App Home や Socket Mode も必須ではありません
- Slack 側の設定は、OAuth と必要な scopes を中心に合わせれば動きます
.env.exampleを.envにコピー- 以下を設定
GAS_WEB_APP_URL: Apps Script の WebアプリURLFRONTEND_API_SHARED_SECRET: GAS側と同じ値NGROK_AUTHTOKEN: ngrokのトークン
例:
GAS_WEB_APP_URL=https://script.google.com/macros/s/XXXX/exec
FRONTEND_API_SHARED_SECRET=replace-with-long-random-secret
NGROK_AUTHTOKEN=replace-with-ngrok-authtoken.env はGit管理対象外です(.gitignore で除外)。
Cloudflare Pages では、ローカルの .env をアップロードせず、Pagesの環境変数機能で値を設定します。
Cloudflare Pages で新規プロジェクトを作成し、GitHubリポジトリを接続して以下を設定してください。
- Framework preset: Next.js
- Root directory:
frontend - Build command:
npm run build - Build output directory:
.next
※ Next.js向け設定が自動検出される場合は、その値を優先して問題ありません。
Cloudflare Pages の Project Settings → Environment Variables で、以下を設定してください(Production/Preview 両方推奨)。
GAS_WEB_APP_URLFRONTEND_API_SHARED_SECRET
これにより、フロントエンドからGASへ送る全APIリクエストに共有シークレットが付与され、 GAS側で未認証リクエストを拒否します。
- ローカル開発用の
.envはGit管理対象外です。 - 本番・プレビュー用の値は、Cloudflare Pages の Environment Variables にのみ設定してください。
- リポジトリにはサンプルとして
.env.exampleのみを置きます。
デプロイ後、Pagesの公開URLで以下を確認してください。
- 画面表示ができること
- ログインなどAPI通信が成功すること
- GAS側で
Unauthorized requestが出ていないこと
docker compose build
docker compose upこれで next と ngrok が起動します。
- アプリ:
http://localhost:3333 - ngrok管理画面:
http://localhost:4040
Slack認証などで公開URLが必要な場合に使います。
.envにNGROK_AUTHTOKENを設定docker compose build && docker compose upで起動- 公開URL確認
- ターミナル出力、または
http://localhost:4040のngrok管理画面から確認
補足: NGROK_AUTHTOKEN が未設定でもcompose起動は継続します(ngrokトンネルは無効化)。
Next.js側は機能ごとに分割済みです。
- 認証:
frontend/components/auth - レイアウト:
frontend/components/layout - 共通UI:
frontend/components/common - タブ機能:
frontend/components/tabs - APIクライアント:
frontend/lib/api.ts
現在、主要機能は次の状態です。
- 実装済み: ログイン、DM送信、チャンネル招待、マイページ基本更新
- 段階移行: 名簿、アンケート、集金(既存GAS APIを使って順次移行)