Files
website-enchun-mgr/docs/prd/04-technical-constraints.md
pkupuk f6b806617e docs: add research assets, screenshots and guides
Include supplementary documentation, research notes on Lexical/UX, and setup guides.
2026-02-11 11:51:35 +08:00

13 KiB

4. Technical Constraints and Integration Requirements

Last Updated: 2025-01-29

This section defines how the migration integrates with the existing architecture and technical constraints.


Existing Technology Stack

Target System Architecture

Languages:

  • TypeScript 5.x (strict mode enabled)

Frameworks:

  • Frontend: Astro 6.0.x (SSR mode + Cloudflare native runtime)
  • Backend/CMS: Payload CMS 3.x
  • UI Components: React (for interactive components via @astrojs/react integration)

Database:

  • Development: Local MongoDB or SQLite
  • Production: MongoDB (Atlas or self-hosted)
  • Option: PostgreSQL support available (via @payloadcms/db-postgres)

Infrastructure:

  • Hosting: Cloudflare Pages (frontend)
  • Serverless: Cloudflare Workers (backend API)
  • Storage: Cloudflare R2 (media files)
  • DNS: Cloudflare (existing)
  • CDN: Cloudflare global network + native runtime

External Dependencies:

  • Authentication: Payload CMS built-in authentication
  • Form Processing: Cloudflare Workers (contact form)
  • Analytics: Google Analytics (G-DKBZWCGGZR)
  • Fonts: Google Fonts (Noto Sans TC, Quicksand)
  • Icons: Google Material Icons

Development Tools:

  • Package Manager: pnpm 10.x (workspace)
  • Build Tool: Turborepo 2.x (monorepo management)
  • Code Quality: ESLint, Prettier
  • Testing: Vitest (unit tests), Playwright (E2E)
  • Version Control: Git

Integration Approach

Database Integration Strategy

Payload CMS Collection Design

// Users Collection (with built-in authentication)
{
  email: string;
  role: 'admin' | 'editor';
  name?: string;
  createdAt: Date;
}

// Posts Collection (migrated from "行銷放大鏡集")
{
  title: string;         // 文章標題
  slug: string;         // URL slug
  excerpt?: string;     // 文章簡述
  content: richText;    // 發文內容
  category: relation;   // 文章分類 (link to Categories)
  publishedDate: Date;  // 發文日期
  featuredImage: media; // 強調圖片
  ogImage?: media;      // Open Graph 顯示圖片
  showInFooter: boolean; // 是否放在頁尾
  status: 'draft' | 'published';
}

// Categories Collection (migrated from "文章分類s")
{
  name: string;         // 分類名稱
  slug: string;         // URL slug
  nameEn?: string;      // 英文分類名稱
  order: number;        // 順序
  textColor: string;    // 文字顏色
  backgroundColor: string; // 分類顏色
  parent?: relation;    // Support nested categories (optional)
}

// Portfolio Collection (migrated from "網站設計範本s")
{
  title: string;        // project
  slug: string;         // Slug
  url?: string;         // External link
  image: media;         // 圖片
  description?: string; // description
  websiteType: string;  // 網站類型
  tags?: string[];      // 標籤 (e.g., "一頁式銷售", "客戶預約")
}

// Media Collection
{
  alt?: string;
  caption?: string;
  url: string;          // R2 URL
  filename: string;
  mimeType: string;
  filesize: number;
  width?: number;
  height?: number;
}

Content Migration Strategy

Phase 1: Webflow Export

  1. Export Webflow CMS as JSON/CSV
  2. Export all media files
  3. Document field mappings

Phase 2: Build Migration Script

// migration-script.ts
// 1. Parse Webflow export data
// 2. Transform to Payload CMS API format
// 3. Batch upload to Payload CMS
// 4. Preserve original slugs and URL structure

Phase 3: Media Migration

  1. Download all images/documents
  2. Upload to Cloudflare R2
  3. Update references in Payload CMS

API Integration Strategy

Astro → Payload CMS

// Fetch data from Payload API
const API_URL = import.meta.env.PAYLOAD_CMS_URL;
const API_KEY = import.meta.env.PAYLOAD_CMS_API_KEY;

async function getPosts() {
  const response = await fetch(`${API_URL}/api/posts?depth=1`, {
    headers: { 'Authorization': `users ${API_KEY}` }
  });
  return response.json();
}

Astro → Payload Authentication

// Verify Payload CMS session in Astro
// Payload sets HTTP-only cookies, Astro reads them
export async function middleware({ request, locals }) {
  const user = await verifyPayloadSession(request.headers.get('cookie'));
  locals.user = user;
}

Frontend Integration Strategy

Component Architecture

apps/frontend/src/
├── components/
│   ├── common/              # Shared components
│   │   ├── Header.astro
│   │   ├── Footer.astro
│   │   └── CTAButton.astro
│   ├── layout/              # Layout components
│   │   ├── MainLayout.astro
│   │   └── AdminLayout.astro
│   └── sections/            # Page sections
│       ├── Hero.astro
│       ├── FeatureCards.astro
│       └── ComparisonTable.astro
├── layouts/
│   ├── BaseLayout.astro
│   └── EmptyLayout.astro
├── pages/
│   ├── index.astro
│   ├── about.astro
│   ├── solutions.astro
│   ├── blog/
│   │   ├── index.astro
│   │   └── [slug].astro
│   └── admin/
│       ├── login.astro
│       └── dashboard.astro
└── lib/
    ├── payload.ts           # Payload API client
    ├── auth.ts              # Auth helpers
    └── utils.ts             # Utility functions

Styling Integration

Tailwind CSS Configuration:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Noto Sans TC', 'sans-serif'],
        display: ['Quicksand', 'sans-serif'],
      },
      colors: {
        // Extract brand colors from Webflow CSS
        brand: { /* ... */ }
      }
    }
  }
}

Testing Integration Strategy

Unit Tests:

  • Utility functions
  • Payload CMS hooks
  • API route handlers

E2E Tests:

  • Critical user journeys:
    • Home → About → Contact
    • Blog list → Article detail
    • Login → Edit content
  • Form submissions
  • Authentication flows

Code Organization and Standards

File Structure Approach

Monorepo Structure:

website-enchun-mgr/
├── apps/
│   ├── backend/            # Payload CMS
│   │   ├── src/
│   │   │   ├── collections/
│   │   │   ├── globals/
│   │   │   ├── payload.config.ts
│   │   │   └── server.ts   # Cloudflare Workers entry
│   │   └── package.json
│   └── frontend/           # Astro
│       ├── src/
│       │   ├── components/
│       │   ├── layouts/
│       │   ├── pages/
│       │   └── styles/
│       ├── astro.config.mjs
│       └── package.json
├── packages/
│   └── shared/             # Shared TypeScript utilities
│       ├── src/
│       │   ├── types/
│       │   ├── utils/
│       │   └── constants/
│       └── package.json
├── pnpm-workspace.yaml
├── turbo.json
└── package.json

Naming Conventions

Files/Folders:

  • Components: PascalCase (Header.astro, FeatureCards.astro)
  • Pages: kebab-case (about.astro, marketing-solutions.astro)
  • Utils: camelCase (formatDate.ts, slugify.ts)
  • Constants: UPPER_SNAKE_CASE (API_URL.ts, BREAKPOINTS.ts)
  • Types: PascalCase (Post.ts, User.ts)

Code Naming:

  • Variables/Functions: camelCase
  • Classes/Interfaces/Types: PascalCase
  • Private vars: camelCase with _ prefix (_internalFunction)
  • Booleans: is/has/should prefix (isLoading, hasError)

Coding Standards

TypeScript Configuration:

{
  "compilerOptions": {
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  }
}

ESLint Rules:

  • @typescript-eslint/recommended
  • astro/recommended
  • Custom rules:
    • Max line length: 100
    • No console.log in production
    • Require explicit return types

Import Order:

// 1. External dependencies
import React from 'react';

// 2. Internal shared
import { formatDate } from '@repo/shared/utils';

// 3. Components
import { Header } from '@/components/common/Header.astro';

// 4. Styles
import '@/styles/global.css';

Documentation Standards

  • All components must have JSDoc comments
  • Complex functions must explain purpose, parameters, return values
  • Payload CMS collections must have field descriptions

Deployment and Operations

Build Process Integration

Turborepo Scripts:

{
  "scripts": {
    "dev": "turbo run dev --parallel",
    "build": "turbo run build",
    "lint": "turbo run lint",
    "test": "turbo run test"
  }
}

Build Flow:

  1. Frontend Build:

    cd apps/frontend
    pnpm build
    # Output: dist/
    
  2. Backend Build:

    cd apps/backend
    pnpm build
    # Output: .next/ or build/
    

Deployment Strategy

Cloudflare Pages Configuration:

# wrangler.toml
name = "enchun-frontend"
compatibility_date = "2024-01-01"

[env.production]
routes = [
  { pattern = "/api/*", zone_name = "enchuntw-admin.anlstudio.cc" }
]

CI/CD Pipeline:

  1. Push to main branch → Auto-trigger deployment
  2. Run tests → Stop deployment if failed
  3. Build → Generate optimized production version
  4. Deploy to Cloudflare Pages

Environment Variables:

# .env.production
PAYLOAD_CMS_URL=https://enchuntw-admin.anlstudio.cc
PAYLOAD_CMS_API_KEY=your-production-key
DATABASE_URI=mongodb+srv://...
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key

Domain and DNS:

  • www.enchun.tw → Cloudflare Pages
  • enchuntw-admin.anlstudio.cc → Payload CMS admin

Monitoring and Logging

Cloudflare Analytics:

  • Page views
  • Response times
  • Error rates
  • Geographic distribution

Logging Strategy:

// Unified logging format
import { logger } from '@/lib/logger';

logger.info('User login', { userId, timestamp });
logger.error('API request failed', { endpoint, error });

Error Tracking:

  • Sentry or Cloudflare Web Analytics
  • Capture frontend errors
  • Track API failures

Configuration Management

Environment Variables:

  • .env.local - Local development
  • .env.production - Production
  • All sensitive data in environment variables

Secret Management:

  • Cloudflare Secrets (Workers)
  • GitHub Secrets (CI/CD)
  • Never commit .env files to Git

Risk Assessment and Mitigation

Technical Risks

Risk Impact Probability Mitigation
Payload CMS collection design doesn't match Webflow High Medium Carefully analyze Webflow CMS structure, create complete field mapping table
Content migration data loss High Medium Build migration validation scripts, compare source and target data
SEO traffic drop High Medium Implement complete 301 redirects, monitor Google Analytics
Performance below target (Lighthouse < 95) Medium Low Use WebPageTest and Lighthouse CI for continuous monitoring
Cloudflare Workers limits Medium Low Optimize bundle size, split using edge functions
Payload auth security vulnerabilities High Low Use tested Payload built-in auth, regular security audits
R2 storage cost over budget Medium Low Implement image compression and lazy loading strategies

Integration Risks

Risk Impact Probability Mitigation
Astro SSR + Payload API integration issues High Medium Build dedicated API client layer, implement error handling and retry logic
Monorepo dependency management conflicts Medium Medium Use pnpm workspace strict version control, regular dependency updates
Tailwind CSS vs Webflow style differences Medium High Extract Webflow CSS to Tailwind config, verify with Storybook
Responsive design breakpoint mismatches Medium Low Use same breakpoint definitions, test all device sizes
Font loading causing FOUT/FOIT Low Medium Use font-display: swap, preload critical fonts

Deployment Risks

Risk Impact Probability Mitigation
Deployment downtime affects SEO Medium Low Use zero-downtime deployment, test staging environment first
Environment variable configuration errors High Low Use CI/CD to validate environment variables, implement config checklist
R2 image loading failures High Medium Implement CDN fallback mechanism, monitor R2 availability
DNS switch delays Low Low Configure DNS in advance, gradually migrate traffic

Next Section: Epic and Story Structure