これまでの Next.js ブログサイト構築シリーズをまとめたページは以下の通りです。
前回の第11回では、 Obsidian の画像リンクを Next.js 用に自動変換し、
日本語のノートファイル名と英語の URL を別々に管理できる仕組みを
Node.js スクリプト(convert.js)として作成しました。
これで変換の仕組みは整いました。しかし、まだ実際には記事は公開されていません。
convert.js が変換した記事と画像を VPS に転送し、
ビルドして本番公開するまでを一気につなぐバッチファイル(deploy.bat)が
まだ完成していないためです。
この記事では、convert.js と連携して動く deploy.bat を完成させ、
Obsidian で書いたテスト記事が実際にサイトに公開されるまでの
全工程を一気に解説します。
この記事を読むと、以下のことができるようになります。
convert.jsと連携するdeploy.batを完成させられる- Obsidian でノートを書いて
deploy.batをダブルクリックするだけで記事が公開できる - 画像も含めて自動で転送・公開できる完全な運用フローが整う
- Windows の WSL を使った自動デプロイの仕組みが理解できる
deploy.bat の役割をおさらいする
第11回で作成した convert.js は、以下の処理を担当していました。
① 誤実行防止の確認
② 記事の事前チェック
③ 転送内容の確認
④ Obsidian の画像リンクを Next.js 用に変換する
⑤ 変換済み記事と転送する画像のリストを作成する
convert.js がここまでやってくれますが、実際の転送とビルドはまだ行われていません。
deploy.bat はこの続きを担当します。
⑥ 変換済み記事を VPS の posts フォルダへ転送する
⑦ 使用している画像だけを VPS の public/images フォルダへ転送する
⑧ 削除対象のファイルを VPS から削除する
⑨ VPS 上で deploy.sh を実行してビルドと公開を行う
この2つのファイルが連携することで、はじめてダブルクリックするだけでブログが更新される完全自動化が実現します。
deploy.bat を作成する
メモ帳を開いて、以下の全文をコピー&ペーストします。
貼り付けたら設定値の部分をご自身の環境に合わせて書き換えてください。
「ファイル」→「名前を付けて保存」を選択して、以下の設定で保存します。
- 保存場所:デスクトップ(任意の場所で構いません)
- ファイル名:
deploy.bat - ファイルの種類:すべてのファイル(
.txtにならないよう注意) - 文字コード:ANSI(または Shift-JIS)
文字コードについての注意
バッチファイルは UTF-8 ではなく ANSI(Shift-JIS) で保存してください。
UTF-8 で保存すると、バッチファイル内の日本語の echo 文が文字化けして正しく表示されないことがあります。バッチファイルで日本語を表示させるための設定(chcp 65001)は記述していますが、ファイル自体の文字コードは ANSI にするのが最も確実です。
@echo off
chcp 65001 > nul
rem ============================================================
rem deploy.bat - Next.js Blog Deploy Script
rem ============================================================
rem STEP 1: Run convert.js (check, confirm, convert)
rem STEP 2: Transfer converted posts to VPS
rem STEP 3: Transfer image files to VPS
rem STEP 4: Delete files from VPS
rem STEP 5: Run deploy.sh on VPS (build and publish)
rem ============================================================
rem ------------------------------------------------------------
rem Settings - Change these values to match your environment
rem ------------------------------------------------------------
rem Path to convert.js script
set SCRIPT_PATH=C:\Users\ユーザー名\scripts\convert.js
rem Converted posts folder path (WSL format)
set CONVERTED_POSTS_WSL=/mnt/c/Users/ユーザー名/scripts/converted-posts/
rem Image list file path (WSL format)
set IMAGE_LIST_WSL=/mnt/c/Users/ユーザー名/scripts/image-list.txt
rem Image list file path (Windows format)
set IMAGE_LIST_WIN=C:\Users\ユーザー名\scripts\image-list.txt
rem Delete list file path (Windows format for for-loop)
set DELETE_LIST_WIN=C:\Users\ユーザー名\scripts\delete-list.txt
rem Delete list file path (WSL format)
set DELETE_LIST_WSL=/mnt/c/Users/ユーザー名/scripts/delete-list.txt
rem Obsidian attachments folder path (WSL format)
set ATTACHMENTS_WSL=/mnt/(Obsidianの画像フォルダのWSL形式パス)/
rem VPS connection settings
set VPS_USER=VPSのユーザー名
set VPS_HOST=VPSのIPアドレス
set VPS_PORT=SSHポート番号
set VPS_KEY=~/.ssh/SSH鍵ファイル名
rem VPS folder paths
set VPS_POSTS=~/example-blog/posts/
set VPS_IMAGES=~/example-blog/public/images/
rem Blog URL (split to avoid cmd misinterpretation of //)
set BLOG_URL=https:
set BLOG_URL=%BLOG_URL%//next.example.com
rem ------------------------------------------------------------
rem STEP 1: Run convert.js
rem ------------------------------------------------------------
echo.
echo ============================================
echo STEP 1: 記事の変換処理を開始します
echo ============================================
node %SCRIPT_PATH%
if %ERRORLEVEL% neq 0 (
echo.
echo [中断] 変換処理でエラーが発生しました。
pause
exit /b 1
)
rem ------------------------------------------------------------
rem STEP 2: Transfer converted posts to VPS
rem ------------------------------------------------------------
echo.
echo ============================================
echo STEP 2: 変換済み記事を VPS に転送しています
echo ============================================
wsl rsync -av --delete "%CONVERTED_POSTS_WSL%" "%VPS_USER%@%VPS_HOST%:%VPS_POSTS%" -e "ssh -i %VPS_KEY% -p %VPS_PORT%"
if %ERRORLEVEL% neq 0 (
echo.
echo [中断] 記事の転送に失敗しました。
pause
exit /b 1
)
rem ------------------------------------------------------------
rem STEP 3: Transfer image files to VPS
rem ------------------------------------------------------------
echo.
echo ============================================
echo STEP 3: 画像ファイルを VPS に転送しています
echo ============================================
if not exist "%IMAGE_LIST_WIN%" (
echo 転送する画像ファイルがありません。スキップします。
goto STEP4
)
set IMAGE_EMPTY=true
for /f "usebackq delims=" %%l in ("%IMAGE_LIST_WIN%") do (
set IMAGE_EMPTY=false
)
if "%IMAGE_EMPTY%"=="true" (
echo 転送する画像ファイルがありません。スキップします。
) else (
wsl rsync -av --files-from="%IMAGE_LIST_WSL%" "%ATTACHMENTS_WSL%" "%VPS_USER%@%VPS_HOST%:%VPS_IMAGES%" -e "ssh -i %VPS_KEY% -p %VPS_PORT%"
if %ERRORLEVEL% neq 0 (
echo.
echo [中断] 画像の転送に失敗しました。
pause
exit /b 1
)
)
:STEP4
rem ------------------------------------------------------------
rem STEP 4: Delete files from VPS
rem ------------------------------------------------------------
echo.
echo ============================================
echo STEP 4: 削除対象ファイルを VPS から削除しています
echo ============================================
if not exist "%DELETE_LIST_WIN%" (
echo 削除対象のファイルがありません。スキップします。
goto STEP5
)
set DELETE_EMPTY=true
for /f "usebackq delims=" %%f in ("%DELETE_LIST_WIN%") do (
set DELETE_EMPTY=false
)
if "%DELETE_EMPTY%"=="true" (
echo 削除対象のファイルがありません。スキップします。
) else (
for /f "usebackq delims=" %%f in ("%DELETE_LIST_WIN%") do (
echo 削除中: %%f
wsl ssh -i %VPS_KEY% -p %VPS_PORT% %VPS_USER%@%VPS_HOST% "rm -f %VPS_POSTS%%%f"
)
)
:STEP5
rem ------------------------------------------------------------
rem STEP 5: Run deploy.sh on VPS
rem ------------------------------------------------------------
echo.
echo ============================================
echo STEP 5: VPS でビルドと公開を実行しています
echo ============================================
echo (この処理には1〜2分かかります。しばらくお待ちください)
wsl ssh -i %VPS_KEY% -p %VPS_PORT% %VPS_USER%@%VPS_HOST% "~/deploy.sh"
if %ERRORLEVEL% neq 0 (
echo.
echo [中断] ビルドまたは公開処理に失敗しました。
pause
exit /b 1
)
rem ------------------------------------------------------------
rem Done
rem ------------------------------------------------------------
echo.
echo ============================================
echo デプロイが完了しました!
echo %BLOG_URL%
echo 上記の URL で記事を確認してください。
echo ============================================
echo.
pause
設定値の書き換えガイド
バッチファイルの上部にある設定値の書き換え方を説明します。
SCRIPT_PATH
第11回で作成した convert.js のパスです。
set SCRIPT_PATH=C:\Users\ユーザー名\scripts\convert.js
ユーザー名 の部分はお使いのパソコンのユーザー名に置き換えてください。
CONVERTED_POSTS_WSL など WSL 形式のパス
Windows のパスを WSL(Linux)形式に変換する必要があります。
WSL では Windows の各ドライブに /mnt/ドライブレター/ という形式でアクセスします。
変換のルールは以下の通りです。
| Windows 形式 | WSL 形式 |
|---|---|
C:\Users\ユーザー名\ | /mnt/c/Users/ユーザー名/ |
D:\MyFiles\ | /mnt/d/MyFiles/ |
ドライブレターを /mnt/ の後に小文字で書き、バックスラッシュ(\)をスラッシュ(/)に変換するだけです。
ATTACHMENTS_WSL
Obsidian の画像フォルダのパスを WSL 形式で書きます。
例えば Obsidian の画像フォルダが C:\Users\ユーザー名\Documents\Obsidian\attachments の場合は以下のようになります。
set ATTACHMENTS_WSL=/mnt/c/Users/ユーザー名/Documents/Obsidian/attachments/
VPS_USER・VPS_HOST・VPS_PORT・VPS_KEY
VPS への SSH 接続情報を書きます。
set VPS_USER=VPSのユーザー名
set VPS_HOST=VPSのIPアドレス
set VPS_PORT=SSHのポート番号
set VPS_KEY=~/.ssh/SSH鍵のファイル名
VPS_KEY の ~ は WSL 上のホームディレクトリを指します。第10回で WSL にコピーした SSH 鍵のファイル名を書いてください。
BLOG_URL
完了メッセージに表示するブログの URL です。// を含む URL はバッチファイルで誤動作することがあるため、2つの変数に分けて結合しています。
set BLOG_URL=https:
set BLOG_URL=%BLOG_URL%//next.example.com
next.example.com の部分をご自身のサブドメインに置き換えてください。
各 STEP の動作を理解する
STEP 1:convert.js を実行する
node %SCRIPT_PATH%
node は Node.js のコマンドです。%SCRIPT_PATH% には先ほど設定した convert.js のパスが展開されます。
convert.js が実行されると、確認メッセージ・事前チェック・変換処理がすべて自動で行われます。convert.js が正常に完了すると、以下の2つのファイルが自動で作成されます。
image-list.txt:転送する画像ファイル名の一覧delete-list.txt:VPS から削除するファイル名の一覧
続く if %ERRORLEVEL% neq 0 は「直前のコマンドがエラーで終了した場合」を意味します。%ERRORLEVEL% はコマンドの終了コードを表す特殊変数で、正常終了は 0、エラー終了は 1 以上の値になります。convert.js がエラーや途中キャンセルで終了した場合は、以降の転送処理を行わずにその場で止まります。
STEP 2:変換済み記事を VPS に転送する
wsl rsync -av --delete "%CONVERTED_POSTS_WSL%" "%VPS_USER%@%VPS_HOST%:%VPS_POSTS%" -e "ssh -i %VPS_KEY% -p %VPS_PORT%"
WSL 経由で rsync コマンドを実行しています。各オプションの意味は以下の通りです。
| オプション | 意味 |
|---|---|
-a | ファイルの属性(権限・日時など)を保持してコピーする |
-v | 転送したファイル名を画面に表示する(verbose の略) |
--delete | 転送元にないファイルを転送先から削除する |
-e "ssh ..." | SSH 経由で転送する際の接続設定を指定する |
--delete オプションにより、 Obsidian の posts フォルダから記事を削除した場合、 VPS 上の対応ファイルも自動で削除されます。ただし convert.js の段階でユーザーが削除を承認した記事のみが対象です。
STEP 3:画像ファイルを VPS に転送する
wsl rsync -av --files-from="%IMAGE_LIST_WSL%" "%ATTACHMENTS_WSL%" "%VPS_USER%@%VPS_HOST%:%VPS_IMAGES%" -e "ssh -i %VPS_KEY% -p %VPS_PORT%"
--files-from オプションは「このファイルに書かれているファイル名だけを転送する」という指定です。image-list.txt に記事で使っている画像名が書かれているため、 Obsidian の画像フォルダ全体ではなく必要な画像だけを選んで転送できます。
転送の前に image-list.txt が空かどうかを確認しています。
set IMAGE_EMPTY=true
for /f "usebackq delims=" %%l in ("%IMAGE_LIST_WIN%") do (
set IMAGE_EMPTY=false
)
各部分の意味は以下の通りです。
for /f:ファイルの中身を1行ずつ読み込む命令"usebackq":ダブルクォーテーションで囲まれたファイルパスを正しく読み込むためのオプション。パスにスペースが含まれても正しく動作するようにするための設定delims=:行の区切り文字を指定しないという設定。これにより、行全体を1つの値として読み込む(デフォルトではスペースで分割してしまうため)%%l:読み込んだ1行分の内容が入る変数
IMAGE_EMPTY が最初は true に設定されており、1行でも内容があれば false に切り替わります。
ループ終了後も true のままであればファイルが空と判断して画像転送をスキップします。
STEP 4:削除対象ファイルを VPS から削除する
for /f "usebackq delims=" %%f in ("%DELETE_LIST_WIN%") do (
echo 削除中: %%f
wsl ssh -i %VPS_KEY% -p %VPS_PORT% %VPS_USER%@%VPS_HOST% "rm -f %VPS_POSTS%%%f"
)
delete-list.txt の各行(ファイル名)を読み取り、1件ずつ VPS 上のファイルを削除します。
rm -f は「指定したファイルを強制削除する」 Linux コマンドです。-f は「force(強制)」の略で、ファイルが存在しない場合でもエラーにならずに処理を続けます。
これにより、すでに削除済みのファイルが delete-list.txt に残っていても問題なく動作します。
%VPS_POSTS%%%f の %%%f は %VPS_POSTS% と %%f をつなげた書き方です。
バッチファイルでは % が特殊文字のため、 %%f と書くことで変数 %%f を展開しています。
STEP 5:deploy.sh を実行してビルドと公開を行う
wsl ssh -i %VPS_KEY% -p %VPS_PORT% %VPS_USER%@%VPS_HOST% "~/deploy.sh"
WSL 経由で VPS に SSH 接続し、第10回で作成した deploy.sh を実行します。deploy.sh の中では以下が行われます。
cd ~/example-blog
npm run build
rsync -av --delete ~/example-blog/out/ /var/www/next.example.com/
npm run build で Next.js の本番用ビルドを実行し、生成された静的ファイルを公開フォルダにコピーします。
このビルド処理には通常1〜2分かかります。ビルド中は画面が止まったように見えることがありますが、裏で処理が進んでいますので、完了メッセージが表示されるまでそのままお待ちください。
動作確認:Obsidian からサイトに公開する
全工程を通して動作確認を行います。
テスト記事を準備する
Obsidian の posts フォルダで新しいノートを作成し、テンプレートを適用します。フロントマターに以下のように入力します。
---
title: "はじめてのObsidianからの投稿"
date: "2026-04-15"
slug: "first-obsidian-post"
description: "ObsidianからNext.jsブログに自動公開する仕組みをテストするための記事です。"
ogImage: "/images/テスト用アイキャッチ画像.webp"
draft: true
---
これは Obsidian から Next.js ブログへの初めての投稿テストです。
![[テスト画像.webp|テスト用の画像]]
記事の内容を入力したら、フロントマターの draft 項目のチェックボックスをクリックしてチェックを外し、公開状態にします。
Obsidian のプロパティ画面でチェックを外すと draft: false または draft: の値が空になります。スクリプトは draft: true でない場合は公開対象として処理します。
deploy.bat を実行する
デスクトップの deploy.bat をダブルクリックします。
黒い画面が開き、以下の流れで処理が進みます。
============================================
あなたのブログ名 デプロイツール
============================================
本番サイトへの公開処理を開始します。
続行しますか?(y/n): y
=== 2026-04-15 19:59:48 デプロイ開始 ===
--- 事前チェックを開始します ---
事前チェック:問題なし
--- VPS上の既存ファイルを確認しています ---
=== 転送内容の確認 ===
【新規・更新】
【新規】first-obsidian-post.md(元ファイル: はじめてのObsidianからの投稿.md)
上記の内容で転送を開始します。よろしいですか?(y/n): y
--- 記事の変換処理を開始します ---
変換完了: はじめてのObsidianからの投稿.md → first-obsidian-post.md
画像リスト作成完了: 2件
=== 変換処理が完了しました ===
続いてバッチファイルがVPSへの転送とビルドを実行します。
============================================
STEP 2: 変換済み記事を VPS に転送しています
============================================
sending incremental file list
./
first-obsidian-post.md
============================================
STEP 3: 画像ファイルを VPS に転送しています
============================================
building file list ... done
テスト用アイキャッチ画像.webp
テスト画像.webp
============================================
STEP 4: 削除対象ファイルを VPS から削除しています
============================================
削除対象のファイルがありません。スキップします。
============================================
STEP 5: VPS でビルドと公開を実行しています
============================================
(この処理には1〜2分かかります。しばらくお待ちください)
=== ビルドを開始します ===
...
✓ Generating static pages (5/5) in 246ms
=== デプロイ完了です ===
============================================
デプロイが完了しました!
https://next.example.com
上記の URL で記事を確認してください。
============================================
「デプロイが完了しました!」と表示されたら、ブラウザでサイトにアクセスします。


上のスクリーンショットは、 Obsidian で作成したノートの内容が Next.js のブログサイトにそのまま公開された様子です。日本語のノートファイル名が英語の URL(
/posts/first-obsidian-post)に変換されており、画像も正しく表示されています。
Obsidian のノートがサイトにそのまま表示されたときの達成感は、このシリーズ全体を通じて最も大きなものでした。バッチファイルのダブルクリックから約1〜2分で記事が公開される体験は、 WordPress の管理画面を開いてコピペしていた頃とは比べ物にならないほど快適です。
運用上の注意点
画像ファイルの削除について
現在の仕組みでは、画像ファイルの転送に --delete オプションを使っていません。これは意図的な設計です。
複数の記事で同じ画像を使っている場合に、一方の記事を削除すると画像も削除されてしまい、もう一方の記事で画像が表示されなくなるリスクがあるためです。不要になった画像は手動で VPS から削除してください。
記事の修正・更新について
すでに公開済みの記事を修正したい場合は、 Obsidian でノートを編集して deploy.bat をダブルクリックするだけです。同じ slug のファイルがすでに VPS 上に存在する場合、スクリプトが「更新」として分類して上書き転送します。
=== 転送内容の確認 ===
【更新】first-obsidian-post.md(元ファイル: はじめてのObsidianからの投稿.md)
上記の内容で転送を開始します。よろしいですか?(y/n):
deploy.sh が見つからないエラーが出た場合
STEP 5 で以下のようなエラーが出た場合は、第10回で作成した deploy.sh が VPS 上に存在するか確認してください。
bash: /home/ユーザー名/deploy.sh: No such file or directory
VPS に SSH 接続して以下のコマンドで確認します。
ls ~/deploy.sh
ls は「list」の略で、指定したファイルやフォルダの存在を確認するコマンドです。
ファイルが存在しない場合は、第10回の手順を参考にして deploy.sh を作成してください。
まとめ
今回は、convert.js と連携する deploy.bat を完成させ、Obsidian で書いた記事と画像をダブルクリック1回で Next.js ブログに自動公開できる完全な運用フローを構築しました。
第1回から始まったこのシリーズで目指してきた「 Obsidian で書いてそのままブログに公開する」という目標が、ついにここで現実になりました。
バッチファイルのダブルクリックから約1〜2分で記事が公開される体験は、WordPress の管理画面を開いて原稿をコピペしていた頃とは比べ物にならないほど快適な執筆環境です。
今後は記事の内容を充実させることに集中できるようになりました。
このシリーズが、同じように移行にチャレンジしている非エンジニアの方の参考になれば幸いです。



コメント