デプロイ#
ovellum build は自己完結した dist/ ディレクトリ — HTML + CSS + 約 2KB の JavaScript — を生成します。サーバーも、データベースも、ランタイムもありません。静的ファイルを配信できるものなら何でもこれを配信できます。
つまり「デプロイ」とは、実のところ「dist/ をホストに届ける」だけのことです。このページでは一般的な方法を、シンプルなものから順に説明します。あなたのコードがすでに置かれている場所に合うものを選んでください。
選択肢の一覧#
- セルフホスト — ローカルでビルドし、
dist/を任意の静的ホスト(Nginx、Apache、S3、VPS、あるいはちょっと確認するためのserve)にコピーします。 - GitHub Pages — 2 つのルート: CI ワークフロー、またはローカルからの
gh-pagesプッシュ。 - Cloudflare(Pages / Workers) — リポジトリを接続すると、Cloudflare がプッシュのたびにビルドしてデプロイします。
- その他のプラットフォーム — GitLab Pages、Netlify、Vercel など。同じパターンで、設定ファイルが違うだけです。
セルフホスト#
ベースラインであり、デフォルト: ビルドして、フォルダを静的ファイルを配信する場所に置くだけ。
ovellum build # writes ./dist
そして:
- 任意の Web サーバー(Nginx、Apache、Caddy): ドキュメントルートを
dist/に向けます。 - オブジェクトストレージ(S3、R2、GCS):
dist/の中身をバケットにアップロードし、静的サイト配信を有効にします。 - ちょっとローカルで確認:
npx serve dist。
プリティ URL(<slug>/index.html)はリライトルールなしで動作します — /guides/ へのリクエストは /guides/index.html を配信し、これはどの静的サーバーもデフォルトで行います。ビルドは dist/404.html も書き出します。ホストが not-found ページに対応しているなら、それを設定してください。
出力フォルダを選ぶ#
ovellum build はデフォルトで ./dist に書き込みます。ホストが別のフォルダを期待する場合(public/ を期待するものもあります)、output を設定します。
{
"output": "./public"
}
Ovellum の中で「dist」をハードコードしている箇所はありません。
出荷前に検証する#
ovellum build
npx serve dist
表示された URL を開き、あちこちクリックし、テーマを切り替え、存在しないパスにアクセスして 404 を確認します。ローカルで動くなら、ホスト上でも動きます。
GitHub Pages#
すでに GitHub にあるプロジェクト向け。2 つのルート — どちらか 1 つを選びます。
ルート A — GitHub Actions(推奨)#
ワークフローが main へのプッシュのたびにビルドし、その結果を公開します。ローカルビルドも、追加のブランチも不要です。これがあなたが今読んでいるサイトを公開しているものです。動作するコピーが /.github/workflows/deploy-website.yml にあります。
その形は次のとおりです。
name: Deploy site
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 10 }
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm exec ovellum build
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
そして Settings → Pages → Source を GitHub Actions に設定し、main にプッシュすれば、あとはワークフローが処理します。(pnpm の代わりに npm を使う? pnpm/action-setup のステップを setup-node の cache: npm に差し替え、npm ci + npx ovellum build を実行します。)
ルート B — ローカルビルド + gh-pages ブランチ#
CI なし。ローカルでビルドし、gh-pages ヘルパーで dist/ を gh-pages ブランチに公開します。
ovellum build
npx gh-pages -d dist --dotfiles
-d distはビルド出力を公開します。--dotfilesはCNAMEや.nojekyllのようなドットファイルを含めます。
そして Settings → Pages → Source を Deploy from a branch、ブランチ gh-pages、フォルダ / (root) に設定します。
このルートについて 2 つの注意点:
.nojekyllファイルを追加する。 ブランチベースの Pages は出力を Jekyll に通すため、_で始まるファイルやフォルダが無視されます。空の.nojekyllをinput/ディレクトリに置けば、Ovellum がそれをdist/に通過させ、Jekyll は邪魔をしなくなります。(ルート A ではこれは不要です。Jekyll を通さずにアーティファクトを直接配信するためです。)- 1 コマンドにする。
package.jsonにスクリプトを追加します:"deploy": "ovellum build && gh-pages -d dist --dotfiles"。あとは公開したいときにnpm run deployです。
カスタムドメイン#
input/ ディレクトリの中に、あなたが管理するホスト名を 1 行だけ書いた CNAME ファイルを置きます。
docs.example.com
Ovellum は .md 以外のファイルをそのまま通過させるので、CNAME は dist/CNAME に着地し、Pages が自動的に拾います。あとは DNS を GitHub Pages に向けます。正確な手順は DNS プロバイダーによりますが、Cloudflare が圧倒的に一般的で、これには注意すべき分かりにくい落とし穴が 1 つあります。
Cloudflare 経由の DNS(一般的なケース)#
-
Cloudflare の DNS パネルで、レコードを追加します:
- Type:
CNAME - Name: カスタムドメインのサブドメイン部分
(例:
docs.example.comならdocs、ovellum.oss.oinam.comならovellum.oss) - Target:
<your-user>.github.io(プロトコルなし、パスなし、末尾のドットなし) - Proxy status: DNS only(グレーの雲)。 これが落とし穴です。
- Type:
-
GitHub リポジトリの Settings → Pages で、次を確認します:
- Source が「GitHub Actions」(ルート A)または
gh-pagesブランチ(ルート B)であること。 - Custom domain フィールドに
CNAMEファイルの値が表示されていること。GitHub は最初のデプロイでdist/CNAMEからそれを拾います。
- Source が「GitHub Actions」(ルート A)または
-
数分待ちます。DNS が GitHub のサーバーに解決されると、GitHub Pages はカスタムドメイン用の Let's Encrypt 証明書を自動的に発行します。Enforce HTTPS が利用可能になるまで Pages 設定ページを更新し、利用可能になったらチェックを入れます。
これで完了です — https://docs.example.com/ が HTTPS であなたのサイトを配信するようになりました。
なぜグレーの雲(DNS-only)なのか?#
Cloudflare のプロキシがオン(オレンジの雲)のとき、Cloudflare は SSL 自体を終端し、GitHub Pages の証明書を発行するために Let's Encrypt が送る HTTP-01 チャレンジに自分で応答してしまいます。チャレンジが GitHub に届かず、証明書が発行されず、Pages はそのまま素の github.io URL を配信します。グレーの雲(DNS-only)は Cloudflare のプロキシをバイパスするので、チャレンジが GitHub に直接届きます。
証明書が発行された後なら、あとでオレンジの雲(プロキシオン)に切り替えても構いません。そうする場合は:
- Cloudflare の SSL/TLS モードを Full (strict) に設定します — それ未満だと、Cloudflare が平文を配信したり、下流で無効な証明書について警告したりする恐れがあります。
- GitHub が発行した証明書を無効にしないでください。GitHub Pages はそれを再発行し続けます。訪問者に配信されるのは Cloudflare のエッジ証明書です。
ほとんどのドキュメントサイトでは、グレーの雲で十分です。GitHub Pages はすでに CDN 上にあり、Cloudflare のプロキシ機能はドキュメント用サブドメインには通常オーバースペックです。
その他のプロバイダー経由の DNS#
考え方は同じで、UI が違うだけです。
- Namecheap / GoDaddy / Route 53 など — サブドメインから
<your-user>.github.ioへの CNAME レコードを追加します。プロキシの懸念はありません。 - Apex ドメイン(
docs.example.comではなくexample.com) — ほとんどのプロバイダーは apex での CNAME を許可しません。代わりに GitHub Pages の IP を指す 4 つの A レコードを使います。現在の IP リストについては GitHub のドキュメントを参照してください。
カスタムドメインなしの場合#
サイトは https://<user>.github.io/<repo>/ から配信されます — サブパスに注意してください。site.basePath を設定しないと内部リンクが壊れます。サブパス下でのホスティングを参照してください。
Cloudflare(Pages / Workers)#
あなたのコードが GitHub(または Cloudflare が接続できる任意の git ホスト)にあることを前提とします。Cloudflare はリポジトリを監視し、プッシュのたびにリビルドします — あなたがビルドを実行したり何かをアップロードしたりすることはありません。
- Cloudflare ダッシュボード → Workers & Pages → Create → Pages → Connect to Git。
- リポジトリとプロダクションブランチ(
main)を選びます。 - ビルド設定:
- Build command:
npx ovellum build - Build output directory:
dist - Root directory: 空のままにするか、サイトがモノレポの中にある場合はサブフォルダ(例:
website)に設定します。
- Build command:
- 保存。Cloudflare がビルドしてデプロイし、以降のプッシュは自動的に再デプロイされます。
Cloudflare の CDN がキャッシュと TLS を処理します。Pages と新しい Workers の静的アセットホスティングは同じ「接続してビルド」のフローを共有します — どちらでも動作しますが、ドキュメントサイトには Pages が最もシンプルです。
Cloudflare にビルドさせるのではなく、自分でビルド済みフォルダをプッシュしたい? Wrangler を使います: npx wrangler pages deploy dist。上記の git 接続フローが一般的なケースで、ローカルツールは不要です。
その他のプラットフォーム#
ほかのすべての静的ホストは同じ形に従います: ビルドコマンド npx ovellum build、出力ディレクトリ dist。 ホストにこの 2 つを指定すれば動作します。いくつか具体例を挙げます。
GitLab Pages#
.gitlab-ci.yml をコミットします。GitLab Pages は pages という名前のジョブのアーティファクトを配信し、それが public/ フォルダにあることを期待します — なのでビルド出力をそこに移動します。
pages:
image: node:20
script:
- npx ovellum build
- mv dist public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
GitLab は結果を https://<group>.gitlab.io/<project>/ で配信します — これはサブパスなので、カスタムドメインを追加しない限り site.basePath(下記参照)を設定します。
Netlify#
npx netlify deploy --prod --dir=dist
または netlify.toml をコミットします:
[build]
command = "npx ovellum build"
publish = "dist"
Vercel#
npx vercel --prod dist
または vercel.json:
{
"buildCommand": "npx ovellum build",
"outputDirectory": "dist",
"framework": null
}
それ以外のもの#
Render、Surge、Fly static、社内 CDN — レシピは変わりません。ホストが git からビルドするなら、ビルドコマンド(npx ovellum build)と出力ディレクトリ(dist)を渡します。そうでないなら、ローカルで ovellum build を実行して dist/ をアップロードします。
サブパス下でのホスティング#
サイトがオリジンのルートに置かれない 3 つのケース:
- 既存サイトの一部としてのドキュメント — 例:
example.com/docs/。 - カスタムドメインなしの GitHub Pages —
<user>.github.io/<repo>/。 - カスタムドメインなしの GitLab Pages —
<group>.gitlab.io/<project>/。
どれも同じ修正が必要です: Ovellum にサブパスを伝え、すべての内部リンク、アセット URL、canonical、サイトマップのエントリにプレフィックスを付けられるようにします。site.basePath を設定します。
{
"site": {
"basePath": "/docs",
"baseUrl": "https://example.com"
}
}
ルール:
- 先頭にスラッシュ、末尾にスラッシュなし。
/docs✓、docs✗、/docs/✗。 - 著者はルート相対のリンク(
/getting-started/、/reference/config/)を書き続けます。ビルドがレンダリング時にプレフィックスを追加します。 - デプロイされたサイトは
https://example.com/docs/で到達できます。 baseUrlはオリジンのみ(パスなし)。パスはbasePathにあります。
出力で何が変わるか:
<!-- Without basePath -->
<a href="/getting-started/">Getting started</a>
<link rel="stylesheet" href="/assets/ovellum.css">
<!-- With basePath: "/docs" -->
<a href="/docs/getting-started/">Getting started</a>
<link rel="stylesheet" href="/docs/assets/ovellum.css">
外部リンク、フラグメントのみのリンク(#anchor)、mailto: / 絶対 URL はそのまま通過します。
サイトをスタンドアロン(docs.example.com など)でホストする場合は、basePath を空のままにします — それがデフォルトです。ルート配信のサイトにこれを設定すると、すべてのリンクに誤ってプレフィックスが付いてしまいます。