# 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 ```typescript // 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** ```typescript // 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 ```typescript // 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 ```typescript // 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:** ```javascript // 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:** ```json { "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:** ```typescript // 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:** ```json { "scripts": { "dev": "turbo run dev --parallel", "build": "turbo run build", "lint": "turbo run lint", "test": "turbo run test" } } ``` **Build Flow:** 1. **Frontend Build:** ```bash cd apps/frontend pnpm build # Output: dist/ ``` 2. **Backend Build:** ```bash cd apps/backend pnpm build # Output: .next/ or build/ ``` ### Deployment Strategy **Cloudflare Pages Configuration:** ```toml # 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:** ```bash # .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:** ```typescript // 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](./05-epic-stories.md)