Full website
This commit is contained in:
1 parent
807c43ece5
commit
ea9f33f60e
40 files changed
+4503
-1202
No files matched your search
@@ -0,0 +1,151 @@
|
||||
# Website CMS Parity Plan
|
||||
|
||||
## Goal
|
||||
Bring `apps/website` closer to the Page Builder CMS behavior already used by `apps/spa`, while preserving Next.js SSR/SEO behavior.
|
||||
|
||||
The website should not copy SPA client rendering wholesale. It should use CMS layout sections for editable marketing/content areas, and keep SEO-critical commerce data server-rendered.
|
||||
|
||||
## Scope
|
||||
Allowed implementation scope:
|
||||
- `apps/website/**`
|
||||
- `docs/**`
|
||||
- `implementation_plan.md`
|
||||
|
||||
Do not edit without separate approval:
|
||||
- `apps/spa/**`
|
||||
- `apps/admin/**`
|
||||
- `apps/backend/**`
|
||||
- `packages/types/**`
|
||||
|
||||
If a correct fix requires backend, admin, schema, or shared type changes, report it as a blocker instead of patching around it in website code.
|
||||
|
||||
## Current Website CMS Support
|
||||
Supported in `apps/website`:
|
||||
- `/` fetches `/pages/home`
|
||||
- Website-local `DynamicPageRenderer`
|
||||
- Supported SSR-safe blocks:
|
||||
- `ANNOUNCEMENT_BAR`
|
||||
- `HERO`
|
||||
- `CATEGORIES`
|
||||
- `PRODUCTS`
|
||||
- `PRODUCT_CAROUSEL`
|
||||
- `BANNER`
|
||||
- `TEXT`
|
||||
- `RICH_TEXT`
|
||||
- `NEWSLETTER`
|
||||
- `EDITORIAL_TILE`
|
||||
- `EDITORIAL_CAROUSEL`
|
||||
- `HERO_ARTICLE`
|
||||
- `SCENT_NOTES_BREAKDOWN`
|
||||
- `QUOTE_CALLOUT`
|
||||
- `ACCORDION`
|
||||
- `CONTACT_INFO`
|
||||
|
||||
Not fully supported yet:
|
||||
- Client-island block:
|
||||
- `CONTACT_FORM`
|
||||
- Nested CMS custom pages such as `/campaign/summer`
|
||||
- Route layout CMS parity for shop/category/product/search/coupons/scent guide
|
||||
|
||||
## Route Layout Matrix
|
||||
|
||||
| SPA route | Website route | CMS slug | Status | Implementation notes |
|
||||
|---|---|---:|---|---|
|
||||
| `/` | `/` | `home` | supported-m1 | Server-rendered CMS sections. |
|
||||
| `/shop` | `/shop` | `shop-layout` | supported-m1 | Renders announcement/hero/bottom CMS sections around SSR product grid. |
|
||||
| `/category/:id` | `/category/[id]` | `category-layout` | supported-m1 | Renders announcement/hero/bottom CMS sections around SSR category product grid. |
|
||||
| `/products/:id` | `/products/[id]` | `product-detail-layout` | supported-m1 | Renders announcement/bottom CMS sections around SSR product detail. |
|
||||
| `/search` | `/search` | `search-layout` | supported-m1 | Renders announcement/hero/bottom CMS sections around SSR search form and results. |
|
||||
| `/scent-guide` | `/scent-guide` | `scent-guide-layout` | supported-m1 | Renders announcement/hero/bottom CMS sections around article index and exposes article API error state. |
|
||||
| `/coupons` | `/coupons` | `coupons-layout` | supported-m1 | Renders announcement/hero/bottom CMS sections around SSR coupon grid and exposes coupon API error state. |
|
||||
| `/track` | `/track` | `track-order-layout` | later-phase | Depends on track flow migration. |
|
||||
| `/wishlist` | none | `wishlist-layout` | later-phase | Depends on wishlist route migration. |
|
||||
| `/order/:id` | none | `order-success-layout` | later-phase | Depends on order success flow migration. |
|
||||
| `/:slug` | `[slug]` | page slug | supported-m1 | Server-renders published CMS pages by slug with reserved route collision guard. |
|
||||
|
||||
## CMS Layout Rendering Pattern
|
||||
For SEO-critical routes, use this structure:
|
||||
|
||||
1. Fetch route business data on the server.
|
||||
2. Fetch optional CMS layout page on the server.
|
||||
3. Render `ANNOUNCEMENT_BAR` sections above page content.
|
||||
4. Render `HERO` and `BANNER` sections as editable page header when present.
|
||||
5. Render a safe hardcoded SSR fallback header when CMS header sections are missing.
|
||||
6. Render route business content as SSR HTML.
|
||||
7. Render remaining CMS sections below the business content.
|
||||
|
||||
This keeps marketing-controlled content editable without making product/category/search content client-only.
|
||||
|
||||
## Custom CMS Page Policy
|
||||
|
||||
M1 supports single-segment CMS pages through `apps/website/src/app/[slug]/page.tsx`.
|
||||
|
||||
Reserved slugs are intentionally blocked from CMS catch-all rendering:
|
||||
- `about`
|
||||
- `article`
|
||||
- `category`
|
||||
- `contact`
|
||||
- `coupons`
|
||||
- `faq`
|
||||
- `order`
|
||||
- `products`
|
||||
- `profile`
|
||||
- `search`
|
||||
- `scent-guide`
|
||||
- `shop`
|
||||
- `track`
|
||||
- `wishlist`
|
||||
|
||||
Why:
|
||||
- Existing Next routes should keep their route-specific SSR behavior and metadata.
|
||||
- Commerce/auth routes should not be silently replaced by CMS content.
|
||||
- Nested CMS paths need an explicit admin/backend slug policy before website supports them.
|
||||
|
||||
## Block Support Roadmap
|
||||
|
||||
### Batch A: Layout Blocks Already Present
|
||||
Use existing website renderer:
|
||||
- `ANNOUNCEMENT_BAR`
|
||||
- `HERO`
|
||||
- `BANNER`
|
||||
- `TEXT`
|
||||
- `NEWSLETTER`
|
||||
- `CATEGORIES`
|
||||
- `PRODUCTS`
|
||||
- `PRODUCT_CAROUSEL`
|
||||
|
||||
### Batch B: Content Blocks To Port From SPA
|
||||
Website-local SSR-safe equivalents added:
|
||||
- `EDITORIAL_TILE`
|
||||
- `EDITORIAL_CAROUSEL`
|
||||
- `HERO_ARTICLE`
|
||||
- `SCENT_NOTES_BREAKDOWN`
|
||||
- `QUOTE_CALLOUT`
|
||||
- `ACCORDION`
|
||||
- `CONTACT_INFO`
|
||||
|
||||
### Batch C: Client-Island Blocks
|
||||
Add only after explicit route needs are clear:
|
||||
- `CONTACT_FORM`
|
||||
- newsletter submit behavior
|
||||
- any block requiring browser state, localStorage, LIFF, auth, or cart state
|
||||
|
||||
`CONTACT_FORM` should not simulate successful submission without a real API contract. Keep it unsupported until the website contact submission behavior is defined.
|
||||
|
||||
Decision:
|
||||
- Defer `CONTACT_FORM` for now because the submission endpoint is not ready.
|
||||
- Do not render a fake successful submission state.
|
||||
- Do not create a website-only endpoint workaround.
|
||||
- Revisit only when backend/admin/API ownership for contact submissions is confirmed.
|
||||
|
||||
## Acceptance Criteria
|
||||
- `apps/website` route still renders SEO-critical content on the server.
|
||||
- CMS layout failure does not break commerce content.
|
||||
- Published single-segment CMS pages can render through `/:slug`.
|
||||
- API/data failure for commerce content is visible and not collapsed into a fake empty state.
|
||||
- Unsupported block types are logged in development and documented in this plan.
|
||||
- Lint and production build pass for `apps/website`.
|
||||
- No files outside allowed scope are modified.
|
||||
|
||||
## Current Next Step
|
||||
Skip `CONTACT_FORM` for now and continue with missing website flows such as checkout, order success, tracking, wishlist, and profile.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Website Route Parity Audit
|
||||
|
||||
Scope: read-only comparison of `apps/spa/src/App.tsx` against `apps/website/src/app/**`.
|
||||
|
||||
## Route Matrix
|
||||
|
||||
| SPA route | Website route | Status | Notes |
|
||||
|---|---|---|---|
|
||||
| `/` | `/` | upgraded-m1 | Server-rendered from the CMS page endpoint internally. |
|
||||
| `/shop` | `/shop` | upgraded-m1 | Server-renders product/category content, preserves coupon handoff, and consumes `shop-layout` CMS sections around the product grid. |
|
||||
| `/category/:id` | `/category/[id]` | upgraded-m1 | Server-renders category/product content with dynamic metadata and consumes `category-layout` CMS sections around the product grid. |
|
||||
| `/products/:id` | `/products/[id]` | upgraded-m1 | Server-renders product details and metadata, and consumes `product-detail-layout` CMS sections around the product content. |
|
||||
| `/coupons` | `/coupons` | upgraded-m1 | Uses internal links, consumes `coupons-layout` CMS sections, and exposes coupon API error state. |
|
||||
| `/checkout` | `/checkout` | partial-m1 | Client checkout creates pending orders through `POST /orders`, supports settings shipping fee, promotions, coupon validation, saved addresses, points, local order history, and `checkout-layout` CMS sections. Payment/slip upload remains deferred to `/order/[id]` follow-up. |
|
||||
| `/order/:id` | `/order/[id]` | partial-m1 | Server-renders order status, item summary, tracking number, and `order-success-layout` CMS sections. Payment/upload actions are intentionally deferred. |
|
||||
| `/track` | `/track` | upgraded-m1 | Replaces redirect with order tracking form, `POST /orders/track`, device order history, and `track-order-layout` CMS sections. |
|
||||
| `/wishlist` | `/wishlist` | upgraded-m1 | Client wishlist store now matches SPA storage key, supports add/remove from product cards, and consumes `wishlist-layout` CMS sections. |
|
||||
| `/search` | `/search` | upgraded-m1 | Server-renders search results, guards repeated query params, and consumes `search-layout` CMS sections around the search UI. |
|
||||
| `/scent-guide` | `/scent-guide` | upgraded-m1 | Server-renders article index, consumes `scent-guide-layout` CMS sections, and exposes article API error state. |
|
||||
| `/article/:slug` | `/article/[slug]` | exists-needs-upgrade | Exists with dynamic metadata and `notFound`; needs HTML sanitization review. |
|
||||
| `/profile` | `/profile` | partial-m1 | Client profile dashboard uses SPA-compatible auth storage, order history, address CRUD, contact settings, and `profile-layout` CMS sections. LIFF initialization for website remains a follow-up dependency. |
|
||||
| `/:slug` | `/[slug]` | upgraded-m1 | Server-renders published single-segment CMS pages with reserved route collision guard. |
|
||||
| `*` | default Next behavior | missing | No custom `not-found.tsx` currently exists. |
|
||||
|
||||
## Top Website-Only Risks
|
||||
|
||||
| Risk | Severity | Impact |
|
||||
|---|---|---|
|
||||
| Missing legacy classes/design tokens | High | M1 visual cleanup removed `night-*`, `cyan-glow`, and `glass` from website source classes; remaining visual risk is manual UI verification across breakpoints. |
|
||||
| Hardcoded production URLs | Medium | Initial coupon page issue is fixed; continue checking remaining legacy pages during Phase 6. |
|
||||
| Silent API fallbacks | High | M1 SEO routes now expose explicit error states in key product listing flows; remaining legacy pages still need review. |
|
||||
| Client-only SEO weakness | High | M1 fixed `/shop`, `/category/[id]`, `/search`, `/track`, `/wishlist`, `/profile`, `/checkout`, and read-only `/order/[id]`; remaining auth/payment flows are still later-phase work. |
|
||||
| Client-side pricing trust | High | Checkout follows the SPA contract, but backend still trusts client-provided subtotal, discounts, points, shipping, and total. Server-side pricing validation should be owned by backend before production-grade payment rollout. |
|
||||
| Image optimization debt | Low | M1 intentionally keeps `<img>` until image hosting/CDN policy is finalized; `next/image` should be revisited after `images.remotePatterns` can be configured safely. |
|
||||
|
||||
## Recommended Order
|
||||
|
||||
1. Stabilize website-local data helpers.
|
||||
2. Add website CMS renderer and upgrade `/`.
|
||||
3. Upgrade `/products/[id]`.
|
||||
4. Convert `/shop` and `/category/[id]` to SSR shell plus client islands.
|
||||
5. Add CMS custom `/:slug` support with explicit collision rules.
|
||||
6. Add missing commerce/client routes after SEO pages are stable.
|
||||
Reference in new issue
Block a user