DokployでNext.jsプロジェクトをデプロイする
この記事では、サーバーの購入、Dokployのインストールと設定、直接デプロイ、GitHub Actionsによる自動デプロイを含む、DokployでNext.jsプロジェクトをデプロイするための包括的なガイドを提供し、プロジェクトを迅速に立ち上げるお手伝いをします。
前提条件
デプロイを開始する前に、next.config.mjsに以下の設定を追加することをお勧めします:
const nextConfig = {
output: "standalone", // この行を追加
// その他のコード...
}DokployはDocker上で動作するため、standaloneモードを使用することでビルドイメージのサイズを大幅に削減できます。
Dokployとは
Dokployは、Vercel、Netlify、Railway、Zeaburなどのサービスの代替となる、オープンソースのセルフホスティングPaaS(Platform as a Service)です。

サーバーのセットアップとDokployのインストール
サーバーの購入
Dokployを使用するには、自分でサーバーを購入する必要があります。どのプロバイダーを選択すべきか分からない場合は、hostingerを検討してください。初期プロジェクトには、2コア8GBのVPSで十分で、月額わずか$6.49です。

サーバーの設定
支払い後、画面の指示に従ってVPSのセットアップを完了します。設定が完了すると、ダッシュボードにVPSが実行中であることが表示されます。
次に、ファイアウォールルールを設定します。Hostingerにはデフォルトのファイアウォールルールがなく、すべてのポートが開いているため、セキュリティリスクがあります。ポート22、80、443、3000へのアクセスを許可するファイアウォールルールを作成する必要があります。


Dokployのインストール
VPS Terminalを開きます

SSH経由でVPSにログインし、Dokployのインストールコマンドを実行します:
curl -sSL https://dokploy.com/install.sh | sh
インストールが完了したら、コマンド出力に表示されたアドレスにアクセスして、Dokployダッシュボードにアクセスします。
Dokployの設定
登録とログインの後、まずダッシュボード用のカスタムドメインを設定します:

次に、ドメイン解決プラットフォーム(CloudFlareを例として使用)でこのカスタムドメインのDNSレコードを追加し、Aタイプの解決を選択して、サーバーのIPアドレスを入力します。

DNSが伝播したら、カスタムドメインを通じてDokployダッシュボードにアクセスできます。
最後に、図のようにGitアカウントを接続します:

デプロイオプション1: 直接デプロイ
Dokployは、Vercelのようなビジュアルデプロイインターフェースを提供します。ただし、リソースが制約されたサーバーでは、大規模なビルドによってサーバー自体がメモリ不足でクラッシュまたは再起動する可能性があります。そのため、直接デプロイは小規模プロジェクトにのみ適しています。
Projectを作成し、次にServiceを作成します:


Serviceページに入り、Github Account、Repository、Branchを順番に選択してProviderを設定し、Saveをクリックします:

次に、上部のDeployボタンをクリックします:

環境変数を設定します。変更するたびにプロジェクトを再デプロイする必要があります:

ビルド進行状況を表示

カスタムドメインを設定


ビルドが完了したら、CloudflareでDNSを設定する必要があります:

2つのレコードを追加します:
Aレコード:
your-domain.com -> サーバーのIP
Proxyを有効化
Aレコード:
www.your-domain.com -> サーバーのIP
Proxyを有効化次に、SSL/TLS設定に移動し、FullまたはFlexibleを選択します:

Advanced - Redirectsに移動してリダイレクトを設定します


私はwwwドメインを非wwwドメインにリダイレクトすることを好むので、Redirect to non-wwwを選択しました

これらの設定を完了すると、プロジェクトがDokploy上で正常にデプロイされ、実行されます。コードをプッシュするたびに、自動的に新しいデプロイがトリガーされます。
注意: このアプローチは推奨されません。実際のデプロイには、以下で説明するオプション2を使用してください。
デプロイオプション2: GitHub Actionsでデプロイ(推奨)
このアプローチでは、GitHub ActionsでDockerイメージをビルドします。ビルドが完了した後、Dokployは直接イメージをプルして起動し、サーバーの負荷を大幅に削減します。
初期設定
初期設定は一度だけ行えば、永続的に使用できます。
まず、GitHubでPersonal access tokenを作成します。ここをクリックして、新しいTokenを作成します

作成後、tokenが表示されます。後で必要になるので保存してください。
保存し忘れた場合は、ここに戻り、青いテキストをクリックしてtokenを再生成できます(Regenerate token)


Dokployダッシュボードに戻り、Registryページに移動して、Registryを追加します

- Registry Name: カスタム名
- Username: GitHub ID
- Password: 上で生成したToken
- Registry URL: https://ghcr.io

デプロイ手順
Serviceページに移動し、Advancedを開いて、Cluster Settingsを設定します

作成したばかりのregistryを選択し、Saveをクリックします:

次に、Generalをクリックし、ProviderにDockerを選択し、Docker Imageにghcr.io/[GitHub ID]/[Repo Name]:[Branch]を入力してから、Saveをクリックします:

Deploymentsを開いて、表示されたWebhook URLをコピーします:

コードに戻り、ルートディレクトリに.github/workflows/docker-image.ymlファイルを作成します。これは、Dockerイメージのビルドと公開を自動化するGitHub Actionsワークフロー設定ファイルです:
name: Create and publish a Docker image
on:
push:
branches: ["main"]
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-image:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push Docker image
id: push
timeout-minutes: 25
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ⚠️
# ビルドに必要な環境変数のみを含めることをお勧めします
# NEXT_PUBLIC_で始まる環境変数はvarsを使用
# その他の環境変数はsecretsを使用
build-args: |
NEXT_PUBLIC_SITE_URL=${{ vars.NEXT_PUBLIC_SITE_URL }}
NEXT_PUBLIC_PRICING_PATH=${{ vars.NEXT_PUBLIC_PRICING_PATH }}
NEXT_PUBLIC_OPTIMIZED_IMAGES=${{ vars.NEXT_PUBLIC_OPTIMIZED_IMAGES }}
NEXT_PUBLIC_LOGIN_MODE=${{ vars.NEXT_PUBLIC_LOGIN_MODE }}
NEXT_PUBLIC_GITHUB_CLIENT_ID=${{ vars.NEXT_PUBLIC_GITHUB_CLIENT_ID }}
NEXT_PUBLIC_GOOGLE_CLIENT_ID=${{ vars.NEXT_PUBLIC_GOOGLE_CLIENT_ID }}
NEXT_PUBLIC_TURNSTILE_SITE_KEY=${{ vars.NEXT_PUBLIC_TURNSTILE_SITE_KEY }}
NEXT_PUBLIC_ENABLE_STRIPE=${{ vars.NEXT_PUBLIC_ENABLE_STRIPE }}
NEXT_PUBLIC_DEFAULT_CURRENCY=${{ vars.NEXT_PUBLIC_DEFAULT_CURRENCY }}
NEXT_PUBLIC_GOOGLE_ID=${{ vars.NEXT_PUBLIC_GOOGLE_ID }}
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=${{ vars.NEXT_PUBLIC_PLAUSIBLE_DOMAIN }}
NEXT_PUBLIC_PLAUSIBLE_SRC=${{ vars.NEXT_PUBLIC_PLAUSIBLE_SRC }}
NEXT_PUBLIC_DISCORD_INVITE_URL=${{ vars.NEXT_PUBLIC_DISCORD_INVITE_URL }}
NEXT_PUBLIC_AUTO_FILL_AI_PROVIDER=${{ vars.NEXT_PUBLIC_AUTO_FILL_AI_PROVIDER }}
NEXT_PUBLIC_AUTO_FILL_AI_MODEL_ID=${{ vars.NEXT_PUBLIC_AUTO_FILL_AI_MODEL_ID }}
NEXT_PUBLIC_DAILY_AI_AUTO_FILL_LIMIT=${{ vars.NEXT_PUBLIC_DAILY_AI_AUTO_FILL_LIMIT }}
NEXT_PUBLIC_DAILY_SUBMIT_LIMIT=${{ vars.NEXT_PUBLIC_DAILY_SUBMIT_LIMIT }}
NEXT_PUBLIC_DAILY_IMAGE_UPLOAD_LIMIT=${{ vars.NEXT_PUBLIC_DAILY_IMAGE_UPLOAD_LIMIT }}
R2_PUBLIC_URL=${{ secrets.R2_PUBLIC_URL }}
R2_ACCOUNT_ID=${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID=${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY=${{ secrets.R2_SECRET_ACCESS_KEY }}
R2_BUCKET_NAME=${{ secrets.R2_BUCKET_NAME }}
DATABASE_URL=${{ secrets.DATABASE_URL }}
BETTER_AUTH_SECRET=${{ secrets.BETTER_AUTH_SECRET }}
BETTER_AUTH_GITHUB_CLIENT_SECRET=${{ secrets.BETTER_AUTH_GITHUB_CLIENT_SECRET }}
GOOGLE_CLIENT_SECRET=${{ secrets.GOOGLE_CLIENT_SECRET }}
STRIPE_SECRET_KEY=${{ secrets.STRIPE_SECRET_KEY }}
STRIPE_PUBLISHABLE_KEY=${{ secrets.STRIPE_PUBLISHABLE_KEY }}
STRIPE_WEBHOOK_SECRET=${{ secrets.STRIPE_WEBHOOK_SECRET }}
STRIPE_CUSTOMER_PORTAL_URL=${{ secrets.STRIPE_CUSTOMER_PORTAL_URL }}
RESEND_API_KEY=${{ secrets.RESEND_API_KEY }}
RESEND_AUDIENCE_ID=${{ secrets.RESEND_AUDIENCE_ID }}
ADMIN_EMAIL=${{ secrets.ADMIN_EMAIL }}
ADMIN_NAME=${{ secrets.ADMIN_NAME }}
UPSTASH_REDIS_REST_URL=${{ secrets.UPSTASH_REDIS_REST_URL }}
UPSTASH_REDIS_REST_TOKEN=${{ secrets.UPSTASH_REDIS_REST_TOKEN }}
OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY }}
PLAUSIBLE_API_KEY=${{ secrets.PLAUSIBLE_API_KEY }}
PLAUSIBLE_URL=${{ secrets.PLAUSIBLE_URL }}
DISCORD_SUBMIT_WEBHOOK_URL=${{ secrets.DISCORD_SUBMIT_WEBHOOK_URL }}
FIRECRAWL_API_KEY=${{ secrets.FIRECRAWL_API_KEY }}
- name: Trigger dokploy redeploy
# ⚠️ Dokploy deploymentsのWebhook URLを使用
run: |
curl -X GET https://xxxxx注意:
NEXT_PUBLIC_で始まる環境変数はvars参照を使用- その他の環境変数は
secrets参照を使用 - 最後のhttpsアドレスをDokploy deploymentsに表示されたWebhook URLに置き換えてください
次に、ルートディレクトリにDockerfileを作成します。これはDockerイメージのビルド方法を定義します:
# ============================================
# Dependencies Stage
# ============================================
FROM node:20-alpine AS deps
WORKDIR /app
# corepackを有効化(パッケージマネージャーバージョンの管理用)
RUN corepack enable
# パッケージ管理ファイルをコピー
COPY package.json pnpm-lock.yaml* ./
# キャッシュマウントを使用して依存関係をプリフェッチ
RUN --mount=type=cache,target=/root/.local/share/pnpm/store/v3 \
pnpm fetch
# キャッシュマウントを使用して依存関係をインストール(frozen lockfile、オフラインモード)
RUN --mount=type=cache,target=/root/.local/share/pnpm/store/v3 \
pnpm install --frozen-lockfile --offline
# ============================================
# Build Stage
# ============================================
FROM node:20-alpine AS builder
WORKDIR /app
# corepackを有効化
RUN corepack enable
# dependencies stageからnode_modulesをコピー
COPY --from=deps /app/node_modules ./node_modules
# すべてのソースコードをコピー
COPY . .
# ============================================
# Build Arguments
# ビルド時に必要な変数のみを宣言
# ============================================
# NEXT_PUBLIC_*変数(クライアント側JavaScriptに埋め込まれます)
ARG NEXT_PUBLIC_SITE_URL
ARG NEXT_PUBLIC_PRICING_PATH
ARG NEXT_PUBLIC_OPTIMIZED_IMAGES
ARG NEXT_PUBLIC_LOGIN_MODE
ARG NEXT_PUBLIC_GITHUB_CLIENT_ID
ARG NEXT_PUBLIC_GOOGLE_CLIENT_ID
ARG NEXT_PUBLIC_TURNSTILE_SITE_KEY
ARG NEXT_PUBLIC_ENABLE_STRIPE
ARG NEXT_PUBLIC_DEFAULT_CURRENCY
ARG NEXT_PUBLIC_GOOGLE_ID
ARG NEXT_PUBLIC_PLAUSIBLE_DOMAIN
ARG NEXT_PUBLIC_PLAUSIBLE_SRC
ARG NEXT_PUBLIC_DISCORD_INVITE_URL
ARG NEXT_PUBLIC_AUTO_FILL_AI_PROVIDER
ARG NEXT_PUBLIC_AUTO_FILL_AI_MODEL_ID
ARG NEXT_PUBLIC_DAILY_AI_AUTO_FILL_LIMIT
ARG NEXT_PUBLIC_DAILY_SUBMIT_LIMIT
ARG NEXT_PUBLIC_DAILY_IMAGE_UPLOAD_LIMIT
# R2_PUBLIC_URLはnext.config.mjsのimage remotePatternsに必要
ARG R2_PUBLIC_URL
ARG R2_ACCOUNT_ID
ARG R2_ACCESS_KEY_ID
ARG R2_SECRET_ACCESS_KEY
ARG R2_BUCKET_NAME
# DATABASE_URLはビルド時の静的サイト生成(SSG)に必要
ARG DATABASE_URL
# BETTER_AUTH
ARG BETTER_AUTH_SECRET
ARG BETTER_AUTH_GITHUB_CLIENT_SECRET
ARG GOOGLE_CLIENT_SECRET
# STRIPE
ARG STRIPE_SECRET_KEY
ARG STRIPE_PUBLISHABLE_KEY
ARG STRIPE_WEBHOOK_SECRET
ARG STRIPE_CUSTOMER_PORTAL_URL
# RESEND
ARG RESEND_API_KEY
ARG RESEND_AUDIENCE_ID
ARG ADMIN_EMAIL
ARG ADMIN_NAME
# UPSTASH
ARG UPSTASH_REDIS_REST_URL
ARG UPSTASH_REDIS_REST_TOKEN
# AI
ARG OPENROUTER_API_KEY
ARG FIRECRAWL_API_KEY
# PLAUSIBLE
ARG PLAUSIBLE_API_KEY
ARG PLAUSIBLE_URL
# DISCORD
ARG DISCORD_SUBMIT_WEBHOOK_URL
# ============================================
# Build Environment Variables
# ============================================
# NEXT_PUBLIC_*を環境変数として設定し、Next.jsがバンドルに埋め込めるようにする
ENV NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL}
ENV NEXT_PUBLIC_PRICING_PATH=${NEXT_PUBLIC_PRICING_PATH}
ENV NEXT_PUBLIC_OPTIMIZED_IMAGES=${NEXT_PUBLIC_OPTIMIZED_IMAGES}
ENV NEXT_PUBLIC_LOGIN_MODE=${NEXT_PUBLIC_LOGIN_MODE}
ENV NEXT_PUBLIC_GITHUB_CLIENT_ID=${NEXT_PUBLIC_GITHUB_CLIENT_ID}
ENV NEXT_PUBLIC_GOOGLE_CLIENT_ID=${NEXT_PUBLIC_GOOGLE_CLIENT_ID}
ENV NEXT_PUBLIC_TURNSTILE_SITE_KEY=${NEXT_PUBLIC_TURNSTILE_SITE_KEY}
ENV NEXT_PUBLIC_ENABLE_STRIPE=${NEXT_PUBLIC_ENABLE_STRIPE}
ENV NEXT_PUBLIC_DEFAULT_CURRENCY=${NEXT_PUBLIC_DEFAULT_CURRENCY}
ENV NEXT_PUBLIC_GOOGLE_ID=${NEXT_PUBLIC_GOOGLE_ID}
ENV NEXT_PUBLIC_PLAUSIBLE_DOMAIN=${NEXT_PUBLIC_PLAUSIBLE_DOMAIN}
ENV NEXT_PUBLIC_PLAUSIBLE_SRC=${NEXT_PUBLIC_PLAUSIBLE_SRC}
ENV NEXT_PUBLIC_DISCORD_INVITE_URL=${NEXT_PUBLIC_DISCORD_INVITE_URL}
ENV NEXT_PUBLIC_AUTO_FILL_AI_PROVIDER=${NEXT_PUBLIC_AUTO_FILL_AI_PROVIDER}
ENV NEXT_PUBLIC_AUTO_FILL_AI_MODEL_ID=${NEXT_PUBLIC_AUTO_FILL_AI_MODEL_ID}
ENV NEXT_PUBLIC_DAILY_AI_AUTO_FILL_LIMIT=${NEXT_PUBLIC_DAILY_AI_AUTO_FILL_LIMIT}
ENV NEXT_PUBLIC_DAILY_SUBMIT_LIMIT=${NEXT_PUBLIC_DAILY_SUBMIT_LIMIT}
ENV NEXT_PUBLIC_DAILY_IMAGE_UPLOAD_LIMIT=${NEXT_PUBLIC_DAILY_IMAGE_UPLOAD_LIMIT}
# R2
ENV R2_PUBLIC_URL=${R2_PUBLIC_URL}
ENV R2_ACCOUNT_ID=${R2_ACCOUNT_ID}
ENV R2_ACCESS_KEY_ID=${R2_ACCESS_KEY_ID}
ENV R2_SECRET_ACCESS_KEY=${R2_SECRET_ACCESS_KEY}
ENV R2_BUCKET_NAME=${R2_BUCKET_NAME}
# 静的サイト生成用のDATABASE_URL
ENV DATABASE_URL=${DATABASE_URL}
# BETTER_AUTH
ENV BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
ENV BETTER_AUTH_GITHUB_CLIENT_SECRET=${BETTER_AUTH_GITHUB_CLIENT_SECRET}
ENV GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
# Stripe
ENV STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
ENV STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY}
ENV STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
ENV STRIPE_CUSTOMER_PORTAL_URL=${STRIPE_CUSTOMER_PORTAL_URL}
# RESEND
ENV RESEND_API_KEY=${RESEND_API_KEY}
ENV RESEND_AUDIENCE_ID=${RESEND_AUDIENCE_ID}
ENV ADMIN_EMAIL=${ADMIN_EMAIL}
ENV ADMIN_NAME=${ADMIN_NAME}
# UPSTASH
ENV UPSTASH_REDIS_REST_URL=${UPSTASH_REDIS_REST_URL}
ENV UPSTASH_REDIS_REST_TOKEN=${UPSTASH_REDIS_REST_TOKEN}
# AI
ENV OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
ENV FIRECRAWL_API_KEY=${FIRECRAWL_API_KEY}
# PLAUSIBLE
ENV PLAUSIBLE_API_KEY=${PLAUSIBLE_API_KEY}
ENV PLAUSIBLE_URL=${PLAUSIBLE_URL}
# DISCORD
ENV DISCORD_SUBMIT_WEBHOOK_URL=${DISCORD_SUBMIT_WEBHOOK_URL}
# Next.jsテレメトリを無効化
ENV NEXT_TELEMETRY_DISABLED=1
# アプリケーションをビルド
RUN --mount=type=cache,target=/root/.local/share/pnpm/store/v3 \
pnpm build
# ============================================
# Runtime Stage
# ============================================
FROM node:20-alpine AS runner
WORKDIR /app
# ============================================
# ここではビルド引数や環境変数は不要
# すべてのランタイムシークレットはコンテナランタイム(dokploy)によって注入されます
# Next.js standaloneモードはランタイムで環境変数を読み取ります
# ============================================
# 本番環境を設定
ENV NODE_ENV=production
# Next.jsテレメトリを無効化
ENV NEXT_TELEMETRY_DISABLED=1
# システムユーザーグループとユーザーを作成(安全な実行のため)
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# buildステージから必要なファイルをコピー
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# 非rootユーザーに切り替え
USER nextjs
# ポートを公開
EXPOSE 3000
# ポートとホスト名を設定
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# アプリケーションを起動
CMD ["node", "server.js"]docker-image.yml、Dockerfile、GitHub Actionsを設定する際、重要なセキュリティ原則を理解する必要があります:
- プライベートプロジェクト: イメージは通常自分だけがアクセスできるため、ファイルとGitHub Actionsにすべての環境変数を安全に含めることができ、ビルド時変数とランタイム変数を区別することを心配する必要はありません
- オープンソースプロジェクトまたは公開イメージのプロジェクト: 機密情報が漏洩しないように、ファイルとGitHub Actionsにはビルド時の環境変数のみを含めることをお勧めします
- イメージが公開か非公開かは
https://github.com/users/[あなたのGithubユーザー名]/packages/container/[プロジェクトリポジトリ名]/settingsで確認できます

ベストプラクティスとして、ルートディレクトリに.dockerignoreファイルを追加することもできます:
.git
.github
node_modules
.nextdocker-image.ymlとDockerfileで宣言した環境変数を確認した後、GitHub Actionsのsecretsとvariablesで定義する必要があります:

NEXT_PUBLIC_で始まる環境変数をVariablesで定義NEXT_PUBLIC_プレフィックスのない環境変数をSecretsで定義


ランタイムで必要な環境変数は、DokployのEnvironmentで設定する必要があります:

便宜上、ここですべての環境変数を直接コピーすることができます。
コードをプッシュすると、GitHub Actionsビルドプロセスがトリガーされます。ビルドが完了すると、Dokployは自動的に最新のイメージをプルし、プロジェクトの更新を完了します。

コード更新なしで再ビルドする必要がある場合は、GitHub Actionsでビルドプロセスを手動でトリガーできます:

デプロイにDokployを選択するタイミング
Dokployを使用するには自分でサーバーを維持する必要があるため、ほとんどの状況では問題ありませんが、問題が発生した場合、DevOps経験のない人には解決が困難です。したがって、Vercelでのデプロイがコスト効率的でない場合にのみDokployを検討することをお勧めします。例えば、以下のようなシナリオです:
- セキュリティリスクが許容される重要でない製品
- 収益を生み出さない、または利益率の低い製品
- ディレクトリサイトやドキュメントサイトなど、ページ数の多い製品
私個人の使用では、現在Dokployにデプロイしているプロジェクトには以下が含まれます:
- Plausibleなどのサードパーティオープンソースツール
- Nextyドキュメントなどのブログとドキュメントサイト
- Dofollow.Toolsなどのディレクトリサイト
- 軽量な小規模製品
- スケジュールされたタスククローラー