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

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)