---
title: Potola Architecture
---

## 1. 目的

本ドキュメントは、Potola のシステムアーキテクチャおよび採用技術を定義する。

Potola は、

> 写真を飾る静かな画廊

という思想を実現するための写真公開サービスである。

本ドキュメントの目的は、Potola の構成、責務分担、採用技術、データの流れ、設計原則を明確にし、人間の開発者および AI Coding Agent が同じ前提で設計・実装できる状態を作ることである。

具体的な開発 Scope や Phase 固有の技術方針は `phases/` 以下の各 Phase 文書で定義する。

---

## 2. 全体構成

Potola は以下の構成を基本とする。

```text
User Browser
  |
  | HTTPS
  v
SvelteKit Frontend
  |
  | API Request
  v
Cloudflare Workers
  |
  | Auth / DB
  v
Supabase
  |
  | Metadata
  v
PostgreSQL

Cloudflare Workers
  |
  | Object Storage
  v
Cloudflare R2

Cloudflare CDN
  |
  | Public Delivery
  v
Viewer Browser
```

---

## 3. 採用技術・標準バージョン

本セクションを、Potola で使用する採用技術および標準バージョンの正本とする。

| 領域                    | 採用技術                       | 標準バージョン |
| --------------------- | -------------------------- | ------- |
| Runtime               | Node.js                    | 24 LTS  |
| Package Manager       | npm                        | 11.x    |
| Frontend              | SvelteKit                  | 2.60.x  |
| UI Framework          | Svelte                     | 5.56.x  |
| Language              | TypeScript                 | 5.8.x   |
| Build                 | Vite                       | 7.3.x   |
| CSS                   | Tailwind CSS               | 4.1.x   |
| API                   | Cloudflare Workers         | -       |
| Auth                  | Supabase Auth              | -       |
| Database              | Supabase PostgreSQL        | -       |
| Storage               | Cloudflare R2              | -       |
| CDN / Hosting         | Cloudflare                 | -       |
| E2E Test              | Playwright                 | 1.54.x  |
| Unit / Component Test | Vitest                     | 3.2.x   |
| Component Test        | Testing Library for Svelte | 5.x     |
| Performance Test      | Lighthouse CI              | 0.14.x  |
| Repository            | GitHub                     | -       |
| Issue Management      | GitHub Issues              | -       |
| Documentation         | Markdown / Blume           | 2.0.x   |

### 3.1 バージョン運用ルール

- 本ドキュメントに記載された標準バージョンを実装・CIの基準とする。
- 依存関係の更新は、原則としてパッチバージョンの範囲とする。
- メジャーまたはマイナーバージョンを変更する場合は、専用 Issue で影響範囲を確認し、承認後に本ドキュメントを更新する。
- AI Coding Agent は、本ドキュメントに記載された標準バージョンを勝手に変更しない。
- `package.json`、lockfile、CI 設定は、本ドキュメントの標準バージョンと整合させる。
- バージョンに不整合が見つかった場合は、実装を進める前に Issue または Plan で明示する。

### 3.2 TypeScript 基本設定

TypeScript は strict mode を必須とする。

```json
{
  "compilerOptions": {
    "strict": true
  }
}
```

型の詳細なコーディング規約は `04-coding-rules.md` に従う。

### 3.3 CSS 構成

PostCSS および Autoprefixer は標準構成には含めない。

必要になった場合は、技術変更ルールに従って追加する。

### 3.4 CI 基本要件

CI の Node.js は、本セクションで定義する標準バージョンに固定する。

最低限、以下を実行する。

- `npm run check`
- `npm run test`
- `npm run build`

初期セットアップ時に上記スクリプトを定義する。

E2E の具体的な対象範囲は、現在の Phase / Issue で定義する。

---

## 4. 技術別方針

### 4.1 Frontend

採用技術：

- SvelteKit
- TypeScript
- Tailwind CSS

SvelteKit は、軽量でシンプルなフロントエンドを構築しやすい。Potola は複雑な管理画面よりも、写真を美しく見せる閲覧体験を重視する。

方針：

- UI は写真を主役にする
- 過度なアニメーションは避ける
- モバイルブラウザでの閲覧を重視する
- コンポーネントは責務ごとに分割する
- TypeScript を前提とする
- `any` は原則使用しない

### 4.2 Backend / API

採用技術：

- Cloudflare Workers
- TypeScript

Cloudflare Workers は、軽量な API を低コストで運用できるため API 層として採用する。

方針：

- フロントエンドからのデータ操作は原則 Workers API を経由する
- API レスポンス形式は統一する
- 認証・認可チェックは API 側で行う
- 内部エラーをユーザーへ直接返さない
- 重い画像変換処理を Workers に詰め込まない

### 4.3 Authentication

採用技術：

- Supabase Auth

認証方式：

- Google ログイン
- メールログイン

方針：

- 認証済みユーザーのみが写真・アルバムを管理できる
- 公開アルバム閲覧は認証不要とする
- ユーザーは自分の写真・アルバムのみ操作できる
- 認証情報や秘密情報をクライアントに露出しない

### 4.4 Database

採用技術：

- Supabase PostgreSQL

写真、アルバム、ユーザー、公開 URL、写真の並び順など、リレーショナルに管理するデータを保存する。

方針：

- 写真ファイル本体は DB に保存しない
- DB には R2 object key などのメタデータを保存する
- テーブル定義はマイグレーションで管理する
- 公開状態や変換状態は明示的なカラムで管理する

### 4.5 Storage

採用技術：

- Cloudflare R2

方針：

- 写真ファイル本体を保存する
- ブラウザから R2 への直接アップロードを基本とする
- Workers が大きな画像ファイルを直接受け取る構成は避ける
- R2 object key は DB で管理する
- 公開 URL と R2 内部構造を直接結びつけすぎない

### 4.6 CDN / Image Delivery

採用技術：

- Cloudflare CDN

方針：

- 画像配信は静的ファイル配信を基本とする
- 閲覧時に毎回バックエンド処理へ依存する構成は避ける
- キャッシュ制御は公開閲覧ページと画像配信で分けて考える

---

## 5. 基本設計方針

### 5.1 写真ファイルとメタデータを分離する

写真ファイル本体は Cloudflare R2 に保存する。

写真に関するメタデータは Supabase PostgreSQL に保存する。

メタデータには、ファイル名、R2 object key、所有者、アルバム所属、公開状態、作成日時などを含める。

### 5.2 UI から直接 DB を更新しない

フロントエンドは、原則として Cloudflare Workers の API を経由してデータを操作する。

UI から直接 PostgreSQL を更新する実装は避ける。

### 5.3 公開閲覧と管理操作を分離する

管理操作は認証済みユーザーのみが行う。

公開閲覧は、公開 URL を知っている第三者がアクセスできる。

公開閲覧では、管理用 API やユーザーの内部情報を露出しない。

### 5.4 画像配信は CDN を前提とする

公開アルバムの画像表示は、Cloudflare CDN 経由で高速に配信する。

画像閲覧時に毎回バックエンド処理へ依存する構成は避ける。

### 5.5 単純さを優先する

過度な抽象化や将来機能を見越した複雑な設計を避ける。

ただし、将来的な拡張を妨げる密結合は避ける。

---

## 6. 主要コンポーネントの責務

### 6.1 SvelteKit Frontend

主な責務：

- ログイン画面
- 写真アップロード画面
- アルバム作成画面
- アルバム編集画面
- 公開アルバム閲覧画面
- OGP 表示に必要なページ生成
- API 呼び出し
- 入力バリデーション
- ユーザー向けエラー表示

フロントエンドは、ビジネスロジックを過度に持たない。

永続化、認証検証、ファイル保存などの処理は API 側に委譲する。

### 6.2 Cloudflare Workers API

主な責務：

- 認証済みユーザーの確認
- 写真アップロード処理
- R2 連携
- PostgreSQL へのメタデータ登録
- アルバム作成
- アルバムへの写真登録
- 公開 URL 生成
- 公開アルバム情報取得
- API レスポンス整形
- エラーハンドリング

### 6.3 Supabase Auth

ユーザー認証を担当し、発行したユーザー ID を Potola 内の所有者情報と紐づける。

### 6.4 Supabase PostgreSQL

主な管理対象：

- ユーザー情報
- 写真メタデータ
- アルバム情報
- アルバムと写真の関連
- 公開 URL 情報
- 公開状態
- 変換ステータス
- 作成日時・更新日時

### 6.5 Cloudflare R2

写真ファイル本体を object key により管理する。

### 6.6 Cloudflare CDN

公開画像の高速配信とキャッシュ制御を担当する。

---

## 7. データの流れ

### 7.1 ログイン

```text
User
  |
  v
SvelteKit Login Page
  |
  v
Supabase Auth
  |
  v
Session / User ID
```

ログイン後、フロントエンドは認証状態を取得し、API 呼び出し時に認証情報を付与する。

### 7.2 写真アップロード

基本方針は、ブラウザから R2 への直接アップロードを優先する。

```text
User
  |
  v
SvelteKit Upload Page
  |
  +--> Cloudflare Workers API
  |       |
  |       +--> 認証 / メタデータ管理
  |
  +--> Cloudflare R2
          |
          +--> 写真ファイル
```

具体的なアップロード方式は、現在の Phase / Issue で定義する。

### 7.3 アルバム作成

```text
User
  |
  v
SvelteKit Album Page
  |
  v
Cloudflare Workers API
  |
  v
Supabase PostgreSQL
```

### 7.4 公開 URL 生成

```text
User
  |
  v
SvelteKit Album Management Page
  |
  v
Cloudflare Workers API
  |
  v
Supabase PostgreSQL
```

### 7.5 公開アルバム閲覧

```text
Viewer
  |
  v
Public Album Page
  |
  v
Cloudflare Workers API / SvelteKit Load
  |
  v
Supabase PostgreSQL
  |
  v
Cloudflare R2 + CDN
```

---

## 8. データモデル方針

主要テーブル：

### 8.1 users

- id
- auth_user_id
- display_name
- created_at
- updated_at

### 8.2 photos

- id
- owner_user_id
- original_filename
- r2_object_key
- mime_type
- file_size
- width
- height
- created_at
- updated_at

### 8.3 albums

- id
- owner_user_id
- title
- description
- public_id
- visibility
- created_at
- updated_at

### 8.4 album_photos

- id
- album_id
- photo_id
- display_order
- created_at

---

## 9. 公開 URL 設計

公開アルバムは、推測困難な `public_id` を用いて公開する。

```text
https://potola.art/a/{public_id}
```

公開 URL を知っている人が閲覧できる方式を基本とする。

追加の公開方式は、必要に応じて Phase / Issue で定義する。

---

## 10. 画像保存・画像処理方針

R2 の object key は、ユーザー ID や写真 ID をもとに一意に管理する。

例：

```text
users/{user_id}/photos/{photo_id}/original.jpg
users/{user_id}/photos/{photo_id}/display.webp
users/{user_id}/photos/{photo_id}/thumbnail.webp
```

画像最適化方式は、保存写真枚数、月間 PV、平均閲覧数、キャッシュヒット率、転送量、画像変換コスト、運用負荷、画質要件などをもとに判断する。

重い画像変換処理を通常 API リクエスト内で実行しない。

画像変換を導入する場合は、アップロード処理と画像変換処理を分離し、失敗時に再実行できる設計を基本とする。

具体的な導入時期や採用技術は Phase 文書で定義する。

---

## 11. 認証・認可方針

- 管理操作は認証済みユーザーのみが行える
- ユーザーは自分が所有する写真・アルバムのみ操作できる
- 公開閲覧では認証を不要とする
- 公開対象ではないアルバムや写真は閲覧できない

---

## 12. API 設計方針

API は、機能ごとに責務を明確に分ける。

基本 API：

- `POST /api/photos/upload`
- `GET /api/photos`
- `POST /api/albums`
- `GET /api/albums`
- `POST /api/albums/{album_id}/photos`
- `POST /api/albums/{album_id}/publish`
- `GET /api/public/albums/{public_id}`

API レスポンスは共通形式とする。

```ts
type ApiResponse<T> = {
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
  };
};
```

---

## 13. エラー処理方針

ユーザーに対しては、分かりやすいエラーメッセージを表示する。

内部エラー、スタックトレース、R2 object key、DB 内部 ID などは表示しない。

ログには原因調査に必要な情報を残す。

---

## 14. セキュリティ方針

最低限守るべき方針：

- 認証済みユーザーのみが管理操作できる
- 他ユーザーの写真・アルバムを操作できない
- 公開されていない写真は閲覧できない
- アップロード可能なファイル形式を制限する
- ファイルサイズ上限を設定する
- API で内部情報を返さない
- 環境変数や秘密情報をクライアントに露出しない

---

## 15. OGP 方針

公開アルバムページでは OGP を設定する。

基本項目：

- `og:title`
- `og:description`
- `og:image`
- `og:url`

OGP 画像にはアルバム内の代表写真を使用する。

高度な OGP 画像生成を導入する場合は Phase / Issue で定義する。

---

## 16. モバイル対応方針

公開閲覧ページは、モバイルブラウザで快適に閲覧できることを必須とする。

少なくとも以下を満たす。

- スマートフォン幅で崩れない
- 写真が画面幅に応じて表示される
- 余白が過剰にならない
- 読み込みが極端に遅くならない

---

## 17. Development / Repository

採用技術：

- GitHub
- GitHub Issues
- GitHub Pull Requests

開発フローの詳細は `development-workflow.md` で定義する。

---

## 18. Documentation

- 要件整理や背景は DocBase に記録する
- 実装対象は GitHub Issue に落とし込む
- プロジェクト共通ルールは `docs/project-guidelines/` に置く
- Issue には関連する DocBase URL や設計文書 URL を貼る

---

## 19. 技術・バージョン変更のルール

採用技術または標準バージョンを変更する場合は、以下を満たす。

- 変更理由を専用 Issue または ADR に記録する
- Potola Philosophy に反しないこと
- 運用コストが説明できること
- 既存設計への影響を明示すること
- 現在の Scope を不要に拡大しないこと
- メジャー・マイナーバージョン変更では互換性、ビルド、テストへの影響を確認する
- 承認後、実装変更と同時に本ドキュメントの標準バージョンを更新する

一時的な実装都合で、採用技術や標準バージョンを勝手に変更してはならない。

パッチバージョンの更新は許容するが、CI および lockfile との整合性を確認する。

---

## 20. AI Coding Agent への指示

AI Coding Agent は実装時に以下を守る。

- `potola-philosophy.md` の思想を優先する
- 本ドキュメントの構成・採用技術・標準バージョンに従う
- コーディング規約は `04-coding-rules.md` に従う
- Issue に記載された Scope を超えて実装しない
- 現在の開発 Scope で Out of Scope とされた機能を勝手に実装しない
- 判断に迷う場合は実装前に Plan へ明記する

---

## 21. 設計判断の優先順位

設計判断に迷った場合は、以下の順で判断する。

1. `potola-philosophy.md`
2. 本ドキュメント
3. `04-coding-rules.md`
4. GitHub Issue
5. 実装上の都合

Issue よりもプロジェクト全体方針を優先する。

ただし、Issue で明示的に方針変更が承認されている場合は、その Issue の内容を優先する。

---

## 22. まとめ

Potola のアーキテクチャは、写真を安全に保存し、静かに美しく公開するための構成である。

アーキテクチャ、採用技術、標準バージョンの正本は本ドキュメントとする。

Phase 固有の Scope、採用時期、将来候補は `phases/` 以下で管理する。

---

作成日　2026.09.09
