Include supplementary documentation, research notes on Lexical/UX, and setup guides.
476 lines
13 KiB
Markdown
476 lines
13 KiB
Markdown
# 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)
|