Files
homaroma/implementation_plan.md
T
2026-06-17 07:42:59 -04:00

14 KiB

Website SSR Migration Plan

Goal

Upgrade apps/website into the Next.js SSR/SEO version of the current apps/spa experience.

apps/spa is the UX and behavior reference. apps/website is the only application implementation target for this migration.

Scope

Allowed edit scope:

  • apps/website/**
  • planning or handoff documents such as this file

Do not edit without separate approval:

  • apps/spa/**
  • apps/backend/**
  • apps/admin/**
  • packages/types/**

If a correct fix requires backend, schema, shared types, admin CMS, or SPA changes, stop and report it as a blocker instead of using a workaround.

Source Of Truth

  • SPA route map: apps/spa/src/App.tsx
  • SPA home CMS usage: apps/spa/src/pages/HomePage.tsx
  • SPA dynamic renderer: apps/spa/src/components/DynamicPageRenderer.tsx
  • Website API resolver: apps/website/src/lib/api.ts
  • Website App Router pages: apps/website/src/app/**
  • Backend CMS API contract, read-only reference only: apps/backend/src/routes/pages.ts
  • Shared CMS payload schemas, read-only reference only: packages/types/index.ts

Important Clarification

The SPA does not expose a frontend route named /pages/home.

The SPA route / renders HomePage, and HomePage calls the backend CMS API endpoint:

GET ${API_BASE}/pages/home?lang=<current-language>

For apps/website, this means Next pages should keep public SEO routes such as /, /shop, /category/[id], and /products/[id], while using the same CMS API endpoint internally when needed.

Migration Strategy

Do not copy the SPA wholesale into Next.

Use this pattern instead:

  • Server components fetch SEO-critical data and render meaningful initial HTML.
  • Client components handle cart, wishlist, LIFF, forms, filters, payment, and localStorage state.
  • CMS section rendering is adapted into website-local components.
  • Published single-segment CMS pages can be rendered through /:slug without replacing route-specific commerce pages.
  • API/environment logic stays website-local and uses NEXT_PUBLIC_API_URL / INTERNAL_API_URL.

Phase 1: Website Foundation Audit

Owner: frontend-code-auditor review only

Tasks:

  • Build a route parity matrix between apps/spa/src/App.tsx and apps/website/src/app/**.
  • Classify routes as exists-needs-upgrade, missing, client-only-ok, or seo-critical.
  • Identify legacy classes, missing design tokens, hardcoded URLs, and silent API fallbacks in apps/website.
  • Identify pages where current client-only fetch weakens SEO.

Deliverables:

  • Route parity matrix.
  • Website-only risk list.
  • Recommended migration order.

Phase 2: Website Data Layer

Owner: frontend-lead Review: frontend-code-auditor

Tasks:

  • Create or refine website-local fetch helpers under apps/website/src/lib.
  • Separate server-safe fetch helpers from client-only fetch helpers.
  • Ensure all helpers use apps/website/src/lib/api.ts.
  • Add consistent handling for API failures without hiding important contract issues.
  • Avoid importing runtime API constants from @homaroma/types.

Acceptance criteria:

  • No edits outside allowed scope.
  • API helpers work in Next server and client contexts as intended.
  • No silent empty fallback on SEO-critical pages without an explicit fallback reason.

Phase 3: CMS Dynamic Renderer For Website

Owner: frontend-lead Review: frontend-code-auditor

Tasks:

  • Create website-local dynamic page renderer under apps/website/src/components.
  • Adapt these section types first:
    • ANNOUNCEMENT_BAR
    • HERO
    • CATEGORIES
    • PRODUCTS
    • PRODUCT_CAROUSEL
    • BANNER
    • TEXT
    • NEWSLETTER
  • Split SSR-capable sections from client-only interactive sections.
  • Keep payload guards local to apps/website if shared types are insufficient.

Acceptance criteria:

  • Home page can render CMS sections from /pages/home.
  • Unknown section types fail visibly in development logs, but do not crash production rendering.
  • No broad any use unless isolated and documented as a temporary contract gap.

Phase 4: SEO Route Migration

Owner: frontend-lead Review: frontend-code-auditor

Migration order:

  1. /
  2. /products/[id]
  3. /shop
  4. /category/[id]
  5. /article/[slug]
  6. /search

Tasks:

  • Convert SEO-critical content to server-rendered data where possible.
  • Keep interactive controls as client islands.
  • Add or preserve generateMetadata for pages that can provide SEO data.
  • Generate fallback metadata from available API data if CMS metadata is unavailable.

Acceptance criteria:

  • Initial HTML contains meaningful product/category/article/page content.
  • Cart, wishlist, filters, and add-to-cart remain interactive.
  • Build and lint pass for apps/website.

Phase 5: Commerce And LINE OA Client Features

Owner: frontend-lead Review: frontend-code-auditor Flow QA: qa-product-auditor

Routes:

  • /checkout
  • /order/[id]
  • /track
  • /wishlist
  • /profile

Tasks:

  • Adapt SPA behavior into website-local client components.
  • Add website-local auth, wishlist, and LIFF integration if needed.
  • Keep SEO shell/server rendering where useful, but treat these routes as client-heavy flows.
  • Use existing backend API endpoints without changing backend contracts.

Acceptance criteria:

  • Checkout, order success, tracking, wishlist, and profile flows work on desktop and mobile.
  • LINE OA/LIFF logic only runs on the client.
  • Payment/order/upload failures have visible error states.

Phase 6: Visual And UX Alignment

Owner: ux-ui-designer + frontend-lead Review: design-system-auditor

Tasks:

  • Align website visual language with SPA source of truth.
  • Remove or replace legacy website-only classes that are not defined.
  • Align navbar, footer, cart drawer, product card, loading states, empty states, and error states.
  • Check mobile layout and common shopping flows.

Acceptance criteria:

  • Website no longer mixes incompatible legacy dark/cyan styling with SPA visual language.
  • UI remains readable and responsive.
  • Design token usage is consistent within apps/website.

Phase 7: Verification And Release Gate

Owner: orchestrator Reviewers:

  • frontend-code-auditor
  • qa-product-auditor
  • design-system-auditor

Required checks:

  • npm run build -w apps/website
  • npm run lint -w apps/website
  • Manual route smoke test for SEO routes.
  • Manual commerce flow test for checkout/order/tracking.
  • Verify no files outside allowed scope were edited.
  • Verify all blockers requiring backend/schema/shared type changes are reported, not worked around.

Delegation Prompts

Frontend Code Auditor

Use for Phase 1 and review gates.

Review only. Do not edit files.
Inspect apps/website against apps/spa as reference.
Focus on route parity, SSR SEO risks, type/API contract risks, hardcoded values, missing states, and anti-patterns.
Allowed output: findings, severity, file paths, recommended fix, escalation needed.

Frontend Lead

Use for implementation phases.

Implement only inside apps/website.
Use apps/spa as UX and behavior reference, but do not edit apps/spa.
Do not edit apps/backend, apps/admin, or packages/types.
If the correct fix requires those areas, stop and report a blocker.
Preserve Next.js SSR for SEO-critical content and use client islands for interactive behavior.

QA Product Auditor

Use after route groups are implemented.

Review user flows only. Do not edit files unless explicitly asked.
Check broken flows, empty states, error states, mobile behavior, checkout/order/tracking/profile/wishlist flows, and release readiness.

Design System Auditor

Use after visual alignment.

Review visual consistency only. Do not edit files unless explicitly asked.
Check contrast, readability, missing classes, token usage, responsive layout, and SPA/website visual alignment.

Open Decisions

  • Should apps/website support locale-specific URL paths later, or keep language state client-side for now?
  • Should dynamic CMS SEO metadata be generated only from existing API data in this migration?
  • Should apps/spa remain the dedicated LINE OA app after website reaches parity, or should website eventually replace it?
  • Should shared type/runtime cleanup be scheduled as a separate project after website-only migration?
  • Should nested CMS paths such as /campaign/summer be supported, and if yes, what slug policy should admin/backend enforce to avoid collisions with business routes?

Decisions

Image Optimization

Decision: defer migration from <img> to next/image for M1.

Reason:

  • Current image sources are mixed between local public paths such as /images/... and backend/CMS upload paths such as /uploads/....
  • apps/website/next.config.ts does not yet define final images.remotePatterns or production CDN/image host policy.
  • Changing to next/image before image hosting is finalized can create broken remote image rendering or force premature config assumptions.
  • M1 priority is SSR/SEO route parity, API correctness, visual cleanup, and build stability.

Current policy:

  • Keep existing <img> usage for now.
  • Treat @next/next/no-img-element warnings as accepted M1 optimization debt, not a release blocker.
  • Revisit after production image domain/CDN and upload URL strategy are finalized.

Future acceptance criteria for next/image migration:

  • Production image host or CDN is known.
  • apps/website/next.config.ts has explicit images.remotePatterns for allowed hosts.
  • Hero, product primary image, category hero, article cover, and CMS hero/banner images are migrated first.
  • Lint still passes and images render in dev, preview, and production-like environments.

Initial Milestone

M1: Website SEO Foundation

Target:

  • Phase 1 complete.
  • Phase 2 complete.
  • Basic CMS renderer exists in apps/website.
  • / and /products/[id] upgraded first.
  • apps/website build/lint pass.
  • frontend-code-auditor review passed.

Current status:

  • Phase 1 route parity audit documented in docs/website-route-parity-audit.md.
  • Website-local data helpers added under apps/website/src/lib.
  • Website-local result helpers now expose API errors instead of converting every failure into an empty list.
  • CMS layout parity is now wired for /, /shop, /category/[id], /products/[id], /search, /scent-guide, and /coupons.
  • Published single-segment CMS pages now render through apps/website/src/app/[slug]/page.tsx with reserved slug collision protection.
  • Website CMS renderer now supports SSR-safe editorial, article hero, scent notes, quote, FAQ accordion, and contact info blocks.
  • CONTACT_FORM is intentionally deferred until a real submission endpoint/API owner is ready. Do not implement simulated submit behavior.
  • /track now renders the tracking form, calls POST /orders/track, stores validated local order history, and consumes track-order-layout CMS sections.
  • /order/[id] now exists as a read-only SSR order status page with item summary, status, tracking number, metadata, and order-success-layout CMS sections.
  • /wishlist now exists with a website-local persisted wishlist store compatible with SPA homaroma-wishlist, product-card heart toggles, navbar counters, and wishlist-layout CMS sections.
  • /profile now exists with SPA-compatible homaroma-auth-storage, member dashboard, order history, address CRUD, contact settings, navbar profile entry, and profile-layout CMS sections.
  • /checkout now exists with a website-local client checkout, SPA-compatible cart/auth storage, GET /settings, GET /promotions/active, POST /coupons/validate, saved address support, points redemption, POST /orders, local order history, cart clearing, redirect to /order/[id], and checkout-layout CMS sections.

Next implementation target:

  • Run manual commerce QA for /shop -> cart -> /checkout -> /order/[id] -> /track.
  • Confirm website LIFF initialization/auth bootstrap before treating /profile as fully production-ready.
  • Extend /order/[id] payment/slip upload only after explicitly planning the payment side effects and QA gate.
  • Escalate backend server-side pricing validation before treating checkout/payment as production-grade, because the current POST /orders contract trusts client totals, discounts, points, and shipping values.
  • Basic website CMS renderer added under apps/website/src/components/dynamic.
  • / now renders CMS sections from /pages/home internally.
  • /products/[id] now uses website-local data helpers and avoids duplicate product fetch.
  • /shop, /category/[id], and /search now render product/category content on the server instead of client-only fetch.
  • /shop preserves coupon handoff with a client-only localStorage bridge while keeping product content server-rendered.
  • /search guards repeated q query params before trimming.
  • Navbar, Footer, CartDrawer, and legacy content pages now use the website pop-* visual language instead of undefined dark/cyan/glass classes.
  • CMS parity planning added in docs/website-cms-parity-plan.md.
  • /shop now consumes shop-layout CMS sections for announcement, hero/banner, and bottom content around the SSR product grid.
  • /category/[id] now consumes category-layout CMS sections for announcement, hero/banner, and bottom content around the SSR category product grid.
  • /products/[id] now consumes product-detail-layout CMS sections for announcement and bottom content around the SSR product detail.
  • /search now consumes search-layout CMS sections for announcement, hero/banner, and bottom content around SSR search results.
  • /scent-guide now consumes scent-guide-layout CMS sections for announcement, hero/banner, and bottom content around the article index.
  • /scent-guide now exposes article API failure separately from a legitimate empty article list.
  • /coupons now consumes coupons-layout CMS sections for announcement, hero/banner, and bottom content around the SSR coupon grid.
  • /coupons now exposes coupon API failure separately from a legitimate empty coupon list.
  • apps/website CMS parity next target is CMS catch-all custom page support and remaining SPA-only block renderer parity.
  • apps/website lint passes with warnings only.
  • apps/website production build passes.

Remaining M1 follow-up:

  • Final manual browser smoke test of upgraded website routes.
  • Keep remaining <img> usage for M1 and schedule next/image as a later optimization pass after image hosting is finalized.
  • Continue manual visual QA for Navbar, Footer, CartDrawer, and content pages across desktop/mobile breakpoints.