docs: add research assets, screenshots and guides
Include supplementary documentation, research notes on Lexical/UX, and setup guides.
This commit is contained in:
475
docs/prd/04-technical-constraints.md
Normal file
475
docs/prd/04-technical-constraints.md
Normal file
@@ -0,0 +1,475 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user