バックオフィスの全体像 Backoffice at a glance
駐車場シェアリング事業「Parky」の運営をすべてカバーする統合管理ツール。
47 画面 (+ Marketing Portal へ移管 2 画面)・/v1/admin/* の 50+ ルート群・高度なゲーミフィケーション/カスタマイズシステムを持ち、
React 19 + Vite + TypeScript SPA を Cloudflare Pages に配信、データは Cloudflare Workers BFF (Hono + Hyperdrive) 経由で Supabase (PostgreSQL + PostGIS + Auth + Realtime) を叩く構成です。
A unified backoffice that covers every operational aspect of the Parky parking-sharing service.
47 screens (plus 2 redirected to the Marketing Portal), the 50+ /v1/admin/* routes, and a rich gamification / customization system,
built as a React 19 + Vite + TypeScript SPA on Cloudflare Pages. CRUD goes through a Cloudflare Workers BFF (Hono + Hyperdrive) into Supabase (PostgreSQL + PostGIS + Auth + Realtime).
このドキュメントの読み方 How to use this documentation
画面カタログScreen catalog
全 47 画面の一覧。パス・目的・主要UI・操作・呼び出しAPIを完全網羅。
All 47 screens — path, purpose, UI, actions, and called APIs.
機能カテゴリFeature categories
駐車場・ユーザー・売上・ゲーミ等、機能を論理グループ別に把握。
Logical groupings across parking, users, revenue, gamification, and more.
注目機能Highlights
料金エンジン、バッジ条件エンジン、着せ替え、Realtimeなどの深堀り。
Deep dives into the fee engine, badge conditions, theming, realtime, and more.
データモデルData model
主要テーブル、フィールド定義、ER図によるリレーション可視化。
Core tables, field definitions, and an ER diagram of the relationships.
API 仕様 (Redoc)API spec (Redoc)
管理者ポータルが叩く BFF (/v1/admin/*) の OpenAPI 3.1 を Redoc で表示。インタラクティブに叩くなら Swagger UI。
OpenAPI 3.1 of the admin BFF (/v1/admin/*) rendered via Redoc. For interactive calls use Swagger UI.
認証と権限Auth & permissions
Supabase Auth によるログインフローとロール・権限マトリクス。
Login flow via Supabase Auth and the role / permission matrix.
ポータルの位置づけ Where this portal sits
flowchart LR
subgraph Users["利用者 / Consumers"]
EndUser["エンドユーザー
End users"]
Owner["駐車場オーナー
Lot owners"]
end
subgraph Clients["クライアント / Clients"]
Mobile["モバイルアプリ
Mobile app"]
OwnerPortal["オーナーポータル
Owner portal"]
AdminPortal["管理者ポータル
Admin portal
(this doc)"]
end
subgraph Backend["バックエンド / Backend (Supabase)"]
PG[(PostgreSQL
PostGIS)]
Auth[Auth]
RT[Realtime]
Edge[Cloudflare Workers]
end
S3[(Cloudflare R2
assets)]
Map[Mapbox]
EndUser --> Mobile
Owner --> OwnerPortal
AdminPortal -- manages --> Mobile
AdminPortal -- manages --> OwnerPortal
Mobile --> Auth
OwnerPortal --> Auth
AdminPortal --> Auth
Auth --> PG
Mobile --> PG
OwnerPortal --> PG
AdminPortal --> PG
AdminPortal --> RT
AdminPortal --> Edge
Edge --> PG
AdminPortal --> S3
AdminPortal --> Map
対象ユーザー Who uses the portal
| ロールRole | 役割Responsibility |
|---|---|
| システム管理者 (Super Admin)Super Admin | 全機能への無制限アクセス。管理者アカウントやロール定義も行う。 Unrestricted access. Manages admin accounts and role definitions. |
| オペレーションマネージャーOps Manager | 駐車場・ユーザー・売上を日々監視。サポート対応も担当。 Day-to-day monitoring of lots, users, and revenue; handles support escalations. |
| コンテンツマネージャーContent Manager | 記事・広告・ゲーミフィケーション・着せ替えの運営。 Runs articles, ads, gamification, and customization themes. |
| サポートエージェントSupport Agent | サポートチケットと誤情報報告への一次対応。 Front-line handling of support tickets and misinformation reports. |
技術スタック Technology stack
| レイヤLayer | 採用技術Technology |
|---|---|
| フレームワークFramework | React 19 + Vite |
| 言語Language | TypeScript |
| ルーティングRouting | React Router DOM v7(全ページ React.lazy) |
| 状態管理State | AuthContext · CodeProvider · PermissionProvider · PageTitleProvider · I18nProvider · PortalApiProvider + TanStack Query v5 |
| UI | Bootstrap 5 + 独自グラスモーフィズム CSS + Lucide React Icons |
| バックエンドBackend | Cloudflare Workers BFF (/v1/admin/*, Hono) + Supabase (Auth / Realtime / PostgreSQL via Hyperdrive) |
| DB | PostgreSQL 17 + PostGIS(5 schema: public / admin / marketing / analytics / extensions) |
| 認証Auth | Supabase Auth (Email + PW, JWT) — RBAC は admin schema の roles + role_permissions |
| ストレージStorage | Cloudflare R2(presigned PUT、配信は cdn.parky.co.jp) |
| 地図Maps | Mapbox GL JS + mapbox-gl-draw |
| 通知Notifications | FCM v1 API via Cloudflare Workers Queue (parky-fcm-dispatch)。Supabase Edge Functions は不使用 |
| 監視Observability | @sentry/react + PostHog + Cloudflare 構造化ログ |
ディレクトリ構造 Directory layout
parky/web/portal/admin/
├── CLAUDE.md admin ポータル局所ルールAdmin portal local rules
└── src/
├── App.tsx ルート定義 (47 ページ + 2 marketing redirect)Route table (47 pages + 2 marketing redirects)
├── main.tsx エントリーポイントEntry point
├── auth/
│ ├── AuthContext.tsx セッション + アイドルタイムアウト + admin role 検証Session + idle timeout + admin role re-verify
│ ├── RequireAuth.tsx マウント時に /v1/admin/admins/me 再検証Re-verifies via /v1/admin/admins/me on mount
│ └── useAuth.ts
├── lib/
│ ├── bff.ts @parky/bff-client インスタンス@parky/bff-client instance
│ ├── api/ BFF call wrapper(コンポーネント直 fetch 禁止)BFF call wrappers (no direct fetch)
│ ├── queries/ TanStack Query keysTanStack Query keys
│ ├── supabase.ts Auth + Realtime のみ(anon key)Auth + Realtime only (anon key)
│ ├── codes.tsx マスターコード(useCode)Master codes (useCode)
│ └── PageTitleContext.tsx
├── components/
│ ├── layout/ AppLayout / Header / Sidebar / sidebarMenuData / SidebarNotificationsAppLayout / Header / Sidebar / sidebarMenuData / SidebarNotifications
│ ├── ListFilterBar.tsx 共通フィルタバーUniversal filter bar
│ ├── ParkingMap.tsx Mapbox GL JS visualizer
│ ├── ParkingShapeEditor.tsx mapbox-gl-draw shape editor
│ ├── ActivityLogFeed.tsx Realtime feed
│ ├── FileUpload.tsx Cloudflare R2 presigned PUT
│ ├── MarkdownEditor.tsx marked + DOMPurify
│ ├── ConfirmProvider.tsx + ToastProvider.tsx
│ ├── ErrorBoundary.tsx + Forbidden.tsx
│ └── MasterDetailLayout.tsx
├── hooks/
│ ├── PermissionProvider.tsx RBAC ロード + usePermissionRBAC load + usePermission
│ └── …
└── pages/ 47 ページ (全て React.lazy ロード)47 pages (all React.lazy)
最初のログインフロー First login flow
sequenceDiagram participant U as Admin participant FE as Admin Portal (React) participant SB as Supabase Auth participant PG as PostgreSQL U->>FE: email + password FE->>SB: signInWithPassword() SB-->>FE: JWT session FE->>PG: SELECT admins, roles, role_permissions (RLS) PG-->>FE: current admin + permission keys FE-->>U: Dashboard with permitted nav items
React.lazy() で遅延ロードされるため、初回バンドルは小さく、ナビゲーション時にページ単位でコードが取得されます。
Every page is behind React.lazy(), so the initial bundle stays small and code is fetched per-page on navigation.