アーキテクチャArchitecture

Web 版は Astro 5 の SSG(output: 'static')+ Islands 構成です。 ほぼすべてのページをビルド時にレンダリングして静的 HTML として配信し、 検索 UI と地図 UI のみ React Island としてハイドレートします。 配信は Cloudflare Pages(プロジェクト parky-home-dev、カスタムドメイン dev.parky.co.jp)で、 GitHub Actions が wrangler pages deploy で直接送り込みます。

The web app is an Astro 5 SSG build (output: 'static') with Islands. Almost every page is rendered to static HTML at build time; only the search and map UIs hydrate as React islands. Hosting is on Cloudflare Pages (project parky-home-dev, custom domain dev.parky.co.jp), with GitHub Actions running wrangler pages deploy directly.

検索は Pagefind で静的化Search via Pagefind (static index)

/searchPagefindastro-pagefind)でビルド後の dist/ をスキャンして生成される静的インデックスを、クライアントから fetch して全文検索します。ランタイムで Supabase に直接クエリを発行することはありません。

/search is powered by Pagefind (astro-pagefind): the plugin scans the built dist/ after astro build and emits a static index under dist/pagefind/ that the client fetches at runtime. No Supabase queries happen at search time.

Web版のチャネル接続Web app channel view

Web 版だけに関係する接続を抽出した図です。 全体像は 全体アーキテクチャ を参照してください。

The slice of the system the web app touches. For the full picture see the overall architecture.

シェイプをクリックして関連を強調 Click any shape to focus its connections
flowchart LR
  WA["Web App
Astro + Islands"] subgraph Build["ビルド時 (GitHub Actions)"] GHA["GitHub Actions
ランナー"] BUILD["Astro build"] SR["Supabase service_role
(read only)"] end subgraph Runtime["ランタイム (ブラウザ)"] HTML["静的HTML"] ISLAND["検索 / 地図 Island"] ANON["Supabase anon + RLS"] end subgraph Supabase["Supabase"] DB[("PostgreSQL
+ PostGIS")] end subgraph Storage["Object storage (Cloudflare R2)"] WSB["R2 bucket
parky"] end subgraph External["外部"] MB["Mapbox GL JS"] WP["WordPress
media.parky.co.jp"] XSRV["Cloudflare Pages
dev.parky.co.jp"] end GHA --> BUILD BUILD --> SR SR --> DB BUILD --> HTML GHA --> XSRV HTML --> XSRV XSRV --> WA WA --> ISLAND ISLAND --> ANON ANON --> DB WA --> MB ISLAND --> MB WA --> WP HTML --> WSB ISLAND --> WSB

ビルドとデプロイのおおまかな流れBuild & deploy flow (high-level)

sequenceDiagram
  participant GHA as GitHub Actions
  participant API as Workers API
dev-api.parky.co.jp participant Astro as Astro build (@parky/home) participant Supa as Supabase (PostgreSQL) participant PF as Pagefind (postBuild) participant Pages as Cloudflare Pages
parky-home-dev GHA->>API: /v1/hubs/publishable?min=1 (health check, 60s max) GHA->>Astro: npm run build:home Astro->>Supa: getStaticPaths / ページ生成用データ取得 Astro->>API: /v1/* (公開読み取り、CDN キャッシュ経由) Supa-->>Astro: 駐車場・ハブ・シーン等のマスター Astro-->>GHA: dist/ 出力 (静的HTML + Islands JS) GHA->>PF: astro-pagefind が dist/ を走査 PF-->>GHA: dist/pagefind/ (全文検索インデックス) GHA->>Pages: wrangler pages deploy web/home/dist --project-name=parky-home-dev
注: Note: 上の図は流れの概要です。どのページがどのテーブルから getStaticPaths を取るかは個別の Astro ページ (web/home/src/pages/**/*.astro) を直接参照してください。 The sequence above is a high-level summary. Which pages pull from which tables in getStaticPaths is best read directly from each page under web/home/src/pages/**/*.astro.

レンダリング戦略(指針)Rendering strategy (guidance)

注: Note: 以下は 指針であり、各ページの島の配置・client:* ディレクティブの実装状況はページによって差があります。確定情報はソース (web/home/src/pages/**/*.astro, src/components/ParkingMapIsland.tsx, src/components/SearchIsland.tsx 等) を参照してください。 The table below lays out intended patterns. Actual island placement and client:* directives vary per page — see web/home/src/pages/**/*.astro, ParkingMapIsland.tsx, and SearchIsland.tsx for the real layout.
種別TypeExample想定されるハイドレートIntended hydration
トップ / 会社情報 / LPTop / company / LP /, /company, /for-owners/ 原則なし (静的HTML)Static HTML
スポット詳細Spot detail /spot/[id]/, /p/[pref]/[city]/[spotSlug]/ SSG、地図は ParkingMapIsland として島 SSG, map lives as ParkingMapIsland
ハブページHub page /p/[pref]/[city]/ SSG、周辺リスト + 地図 island SSG, neighbourhood list + map island
シーン LPScene LP /scene/[sceneSlug]/ SSG、シーン別の導線 SSG, scene-themed landings
検索Search /search SSG shell + Pagefind 静的インデックスを fetch する SearchIsland SSG shell + a SearchIsland that fetches the Pagefind static index
メディア記事Media articles /media/[...slug]/ MDX、静的のみMDX, static only

Web 版の API エンドポイントWeb-app API endpoints

Astro の SSR アダプタ (@astrojs/cloudflare) 上で src/pages/api/*.ts に置いた APIRoute が Cloudflare Workers として動作します。BFF (dev-api.parky.co.jp) とは別レイヤで、 公開ポータル固有の軽量ユーティリティを担当します。

With the Astro SSR adapter (@astrojs/cloudflare), files under src/pages/api/*.ts export APIRoute handlers that run as Cloudflare Workers. This is a thin utility layer distinct from the BFF (dev-api.parky.co.jp) and serves portal-specific concerns.

エンドポイントEndpoint 目的Purpose 上流Upstream
GET /api/route-eta GET /api/route-eta クエリ o_lng / o_lat / d_lng / d_lat を受け取り、 2 地点間の車移動時間 (渋滞加味) を秒単位で返す。 /search の「到着予想時刻」ボタンが叩く。 レスポンス: { durationSec, distanceM, source: "mapbox" }。 エラー時 400 / 502。Cloudflare edge で 120 秒キャッシュ (Cache-Control: public, max-age=120, s-maxage=120)。 Takes o_lng / o_lat / d_lng / d_lat query params and returns driving-traffic duration in seconds between the two points. Called by the "Arrival ETA" button on /search. Response: { durationSec, distanceM, source: "mapbox" }. Errors: 400 / 502. Cached on the Cloudflare edge for 120 seconds (Cache-Control: public, max-age=120, s-maxage=120). Mapbox Directions API (driving-traffic プロファイル) Mapbox Directions API (driving-traffic profile)
GET /robots.txt GET /robots.txt prod では sitemap を案内、dev / preview は全 Disallow In prod serves sitemap; in dev / preview returns full Disallow

採用技術Tech stack

セキュリティ境界Security boundaries