feat: migrate website-creator from Next.js+Payload to Astro+Tina CMS
Major changes: - Replace Payload CMS with Tina CMS (self-hosted) - Add Astro DB for consent logging (PDPA compliant) - Update Tailwind v3 to v4 (@tailwindcss/vite plugin) - Add astro-tina-starter template - Rewrite consent template for Astro (ConsentBanner.astro, Astro DB, Nano Stores) - Add install-tina-backend.sh for self-hosted Tina per customer - Rename convert-astro.sh to migrate-tina.sh - Add AGENTS.md template for generated websites - Delete all Payload/Next.js files Technical updates: - Astro DB using defineDb with eq operators for queries - Tailwind v4 with @theme block - Tina CMS local development mode - Proper Astro API routes for consent Research-verified with official documentation (April 2026)
This commit is contained in:
@@ -1,61 +1,70 @@
|
||||
# PDPA Consent Logging Template
|
||||
|
||||
Template สำหรับเพิ่ม PDPA consent logging ใน Next.js + Payload CMS (MongoDB)
|
||||
Template สำหรับเพิ่ม PDPA consent logging ใน Astro + Tina (Astro DB)
|
||||
|
||||
## Files
|
||||
|
||||
```
|
||||
consent/
|
||||
├── collections/
|
||||
│ └── ConsentLogs.ts # Payload collection สำหรับ consent logs
|
||||
├── ConsentBanner.astro # Consent banner component
|
||||
├── api/
|
||||
│ └── route.ts # API endpoint สำหรับบันทึก consent
|
||||
├── cookie-banner.tsx # CookieBanner component
|
||||
└── README.md
|
||||
│ └── consent.ts # API endpoints (GET, POST, DELETE)
|
||||
├── db/
|
||||
│ └── config.ts # Astro DB schema (defineTable)
|
||||
├── stores/
|
||||
│ └── consent.ts # Nano Stores for client state
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## วิธีใช้
|
||||
## วิธีใช้ (Astro)
|
||||
|
||||
### 1. เพิ่ม ConsentLogs Collection
|
||||
### 1. เพิ่ม Astro DB Schema
|
||||
|
||||
Copy `collections/ConsentLogs.ts` ไปที่ `src/collections/` ของ project
|
||||
Copy `db/config.ts` ไปที่ `src/db/config.ts`:
|
||||
|
||||
```ts
|
||||
// src/db/config.ts
|
||||
import { defineTable, column } from 'astro:db';
|
||||
|
||||
export const ConsentLog = defineTable({
|
||||
columns: {
|
||||
id: column.number({ primaryKey: true }),
|
||||
action: column.text(),
|
||||
purpose: column.text(),
|
||||
analytics: column.boolean({ default: false }),
|
||||
marketing: column.boolean({ default: false }),
|
||||
functional: column.boolean({ default: false }),
|
||||
userAgent: column.text({ optional: true }),
|
||||
ip: column.text({ optional: true }),
|
||||
timestamp: column.date(),
|
||||
sessionId: column.text({ optional: true }),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### 2. สร้าง API Endpoint
|
||||
|
||||
Copy `api/route.ts` ไปที่ `src/app/api/consent/route.ts`
|
||||
Copy `api/consent.ts` ไปที่ `src/pages/api/consent.ts`
|
||||
|
||||
### 3. เพิ่ม CookieBanner Component
|
||||
### 3. เพิ่ม ConsentBanner Component
|
||||
|
||||
Copy `cookie-banner.tsx` ไปที่ `src/components/`
|
||||
Copy `ConsentBanner.astro` ไปที่ `src/components/consent/ConsentBanner.astro`
|
||||
|
||||
### 4. เพิ่มใน Layout
|
||||
|
||||
เพิ่ม `<CookieBanner />` ใน `src/app/(frontend)/layout.tsx`:
|
||||
เพิ่ม `<ConsentBanner />` ใน `src/layouts/Layout.astro`:
|
||||
|
||||
```tsx
|
||||
import { CookieBanner } from '@/components/cookie-banner'
|
||||
```astro
|
||||
---
|
||||
import ConsentBanner from '../components/consent/ConsentBanner.astro';
|
||||
---
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html>
|
||||
<body>
|
||||
{children}
|
||||
<CookieBanner />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 5. เพิ่ม Collection ใน payload.config.ts
|
||||
|
||||
```ts
|
||||
import ConsentLogs from './collections/ConsentLogs'
|
||||
|
||||
export default buildConfig({
|
||||
collections: [Users, Media, Snacks, Orders, ConsentLogs],
|
||||
// ...
|
||||
})
|
||||
<html lang="th">
|
||||
<body>
|
||||
<slot />
|
||||
<ConsentBanner />
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## API
|
||||
@@ -80,7 +89,7 @@ export default buildConfig({
|
||||
{
|
||||
"success": true,
|
||||
"doc": {
|
||||
"id": "...",
|
||||
"id": 1,
|
||||
"action": "accept",
|
||||
"purpose": "all",
|
||||
"analytics": true,
|
||||
@@ -93,7 +102,46 @@ export default buildConfig({
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/consent
|
||||
|
||||
ดึง consent logs
|
||||
|
||||
```bash
|
||||
curl "http://localhost:4321/api/consent"
|
||||
```
|
||||
|
||||
### DELETE /api/consent
|
||||
|
||||
Right to be forgotten (ลบข้อมูลตาม พ.ร.บ.)
|
||||
|
||||
```bash
|
||||
curl -X DELETE "http://localhost:4321/api/consent?sessionId=xxx"
|
||||
```
|
||||
|
||||
## Nano Stores Usage
|
||||
|
||||
```ts
|
||||
import { consentStore, hasAnalyticsConsent, hasMarketingConsent } from './stores/consent';
|
||||
|
||||
// Subscribe to changes
|
||||
consentStore.subscribe((state) => {
|
||||
console.log('Consent changed:', state);
|
||||
});
|
||||
|
||||
// Check consent
|
||||
if (hasAnalyticsConsent()) {
|
||||
// Load analytics
|
||||
}
|
||||
```
|
||||
|
||||
## UX
|
||||
|
||||
- **ยอมรับทั้งหมด** - เปิดทุกคุกกี้
|
||||
- **ปฏิเสธทั้งหมด** - ปิดทุกคุกกี้ (ยกเว้น functional)
|
||||
- **ตั้งค่าคุกกี้** - แผงปรับแต่งเอง
|
||||
|
||||
## ⚠️ Pitfalls สำคัญ
|
||||
|
||||
1. **ใช้ `mongooseAdapter` ไม่ใช่ `mongodbAdapter`**
|
||||
2. **ConsentLogs ต้องใช้ `export default`** ไม่ใช่ named export
|
||||
1. **Astro DB ต้องรันบน server-side** - ใช้ `APIRoute` import
|
||||
2. **Nano Stores รันบน client-side** - ใช้ `<script>` tag ใน Astro
|
||||
3. **import ถูกต้อง** - ใช้ `import { db } from 'astro:db'` ไม่ใช่ `defineDb`
|
||||
Reference in New Issue
Block a user