- Add Phase 1: Context Gathering with creative brief questions - Add Phase 2: Creative Design (mandatory - multiple directions) - Add Phase 3: Master Plan before execution - Add APPROVAL GATE - wait for user approve before executing - Update questions.md with emotional/target audience questions - Remove Astro DB references from welcome.mdx and index.astro - Focus on unique design, not generic templates
1240 lines
36 KiB
Markdown
1240 lines
36 KiB
Markdown
---
|
||
name: website-creator
|
||
description: สร้างเว็บไซต์เต็มรูปแบบด้วย Astro + Tina CMS พร้อม Workflow สำหรับเว็บใหม่และ Migration ครอบคลุม Design System, Content Collections, Auth, SEO, PDPA Compliance และ Deploy
|
||
tags: [astro, website, website-development, website-creation, migration, tailwindcss, thai, pdpa, seo, tina-cms, image-generation, picture-it]
|
||
category: software-development
|
||
related_skills:
|
||
- spec-driven-development
|
||
- frontend-ui-engineering
|
||
- api-and-interface-design
|
||
- code-review-and-quality
|
||
- performance-optimization
|
||
- browser-testing-with-devtools
|
||
- shipping-and-launch
|
||
---
|
||
|
||
# Website Creator Skill
|
||
|
||
สร้างเว็บไซต์เต็มรูปแบบด้วย Astro + Tina CMS
|
||
|
||
## Architecture
|
||
|
||
**Astro + Tina CMS Stack:**
|
||
- **Astro 6.x** — Static site generator ที่เร็วมาก รองรับ React/Vue/Svelte components
|
||
- **Tina CMS** — Self-hosted Git-based CMS สำหรับ visual content editing
|
||
- **Tailwind CSS 4.x** — ใช้ `@tailwindcss/vite` plugin
|
||
- **External Consent System** — Consent script จาก `consent.moreminimore.com`
|
||
|
||
**Pattern อ้างอิง:** ใช้ template ที่มีอยู่แล้ว: `templates/astro-tina-starter/`
|
||
|
||
### Astro Project Structure
|
||
|
||
```
|
||
src/
|
||
├── components/ # Astro/React components
|
||
├── content/ # Tina CMS content (MDX)
|
||
│ ├── posts/ # Blog posts
|
||
│ ├── pages/ # Static pages
|
||
│ └── settings/ # Site settings (JSON)
|
||
├── layouts/
|
||
│ └── Layout.astro # Main layout
|
||
├── pages/
|
||
│ ├── index.astro # Home page
|
||
│ └── [...slug].astro # Dynamic pages
|
||
├── styles/
|
||
│ └── global.css # Tailwind v4 + @theme
|
||
└── env.d.ts
|
||
|
||
.tina/ # Tina CMS configuration
|
||
├── config.ts # Tina config
|
||
└── schema.ts # Content schema
|
||
|
||
astro.config.mjs # Astro + Tailwind v4 + Tina
|
||
package.json
|
||
```
|
||
|
||
### Static vs SSR
|
||
|
||
- **Static (default):** Pre-built HTML + รันบน CDN
|
||
- **SSR/Hybrid:** ใช้เมื่อต้องการ API routes หรือ dynamic content
|
||
- **Hybrid:** บางหน้า static บางหน้า dynamic
|
||
|
||
**สำหรับ Easypanel:** ใช้ `output: 'static'` หรือ `output: 'hybrid'` (ถ้าต้องการ API routes)
|
||
|
||
## Critical Configuration Rules
|
||
|
||
### 1. astro.config.mjs (Tailwind v4 + Tina)
|
||
|
||
```javascript
|
||
import { defineConfig } from 'astro/config'
|
||
import tailwindcss from '@tailwindcss/vite'
|
||
import tina from 'tinacms'
|
||
|
||
export default defineConfig({
|
||
integrations: [
|
||
tina({
|
||
enabled: !!process.env.TINA_TOKEN,
|
||
sidebar: { partials: [] },
|
||
}),
|
||
],
|
||
vite: {
|
||
plugins: [tailwindcss()], // Tailwind v4 ใช้ @tailwindcss/vite
|
||
},
|
||
output: 'static', // หรือ 'hybrid' ถ้าต้องการ API routes
|
||
})
|
||
```
|
||
|
||
### 2. Required Dependencies
|
||
|
||
```json
|
||
{
|
||
"dependencies": {
|
||
"astro": "^6.1.7",
|
||
"@tinacms/cli": "^2.1.0",
|
||
"tinacms": "^2.2.0"
|
||
},
|
||
"devDependencies": {
|
||
"@tailwindcss/vite": "^4.0.0",
|
||
"tailwindcss": "^4.0.0",
|
||
"@astrojs/mdx": "^4.0.0",
|
||
"typescript": "^5.6.0"
|
||
}
|
||
}
|
||
```
|
||
|
||
**CRITICAL: Tailwind v4 ใช้ `@tailwindcss/vite` plugin ไม่ใช่ `@astrojs/tailwind`**
|
||
|
||
### 3. Tailwind v4 Configuration
|
||
|
||
Tailwind v4 ไม่มี `tailwind.config.js` — ใช้ CSS `@theme` block แทน:
|
||
|
||
```css
|
||
/* src/styles/global.css */
|
||
@import "tailwindcss";
|
||
|
||
@theme {
|
||
/* Fonts */
|
||
--font-sans: "Inter", "Noto Sans Thai", system-ui, sans-serif;
|
||
|
||
/* Colors */
|
||
--color-primary-50: #f8fafc;
|
||
--color-primary-900: #0f172a;
|
||
--color-accent-500: #3b82f6;
|
||
|
||
/* Border Radius */
|
||
--radius-sm: 0.25rem;
|
||
--radius-lg: 0.75rem;
|
||
--radius-xl: 1rem;
|
||
}
|
||
```
|
||
|
||
### 4. Tina CMS Schema
|
||
|
||
```typescript
|
||
// .tina/schema.ts
|
||
import { defineSchema } from 'tinacms'
|
||
|
||
export const schema = defineSchema({
|
||
collections: [
|
||
{
|
||
name: 'post',
|
||
label: 'Posts',
|
||
path: 'src/content/posts',
|
||
format: 'mdx',
|
||
fields: [
|
||
{ type: 'string', name: 'title', label: 'Title', required: true },
|
||
{ type: 'string', name: 'slug', label: 'Slug', required: true },
|
||
{ type: 'datetime', name: 'publishedAt', label: 'Published At' },
|
||
{ type: 'rich-text', name: 'body', label: 'Body', isBody: true },
|
||
],
|
||
},
|
||
{
|
||
name: 'page',
|
||
label: 'Pages',
|
||
path: 'src/content/pages',
|
||
format: 'mdx',
|
||
fields: [
|
||
{ type: 'string', name: 'title', label: 'Title', required: true },
|
||
{ type: 'string', name: 'slug', label: 'Slug', required: true },
|
||
{ type: 'rich-text', name: 'body', label: 'Body', isBody: true },
|
||
],
|
||
},
|
||
],
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
## Workflow A: สร้างเว็บใหม่
|
||
|
||
> ⚠️ **สำคัญ: ต้องวางแผนก่อน + รอ approve ก่อนทำงานเสมอ**
|
||
>
|
||
> ขั้นตอน: Context → Design → Plan → Approve → Execute
|
||
|
||
---
|
||
|
||
### Phase 1: Context Gathering (ถามให้ครบ)
|
||
|
||
**ใช้ `references/questions.md` เป็นแนวทาง แต่ต้องถามให้ลึกกว่า surface level:**
|
||
|
||
#### 1.1 ข้อมูลพื้นฐาน
|
||
```
|
||
1. ชื่อเว็บไซต์/บริษัท?
|
||
2. ทำอะไร? (ขายอะไร/ให้บริการอะไร)
|
||
3. กลุ่มเป้าหมายคือใคร?
|
||
4. มีเว็บอยู่แล้วหรือยัง?
|
||
```
|
||
|
||
#### 1.2 Brand Context (ทำให้ต่างจากคนอื่น)
|
||
```
|
||
5. ทำไมลูกค้าควรเลือกคุณ ไม่ใช่คู่แข่ง?
|
||
6. มี brand story หรือ positioning อะไรที่ต้องสื่อสาร?
|
||
7. มี tone of voice หรือ personality อย่างไร? (เช่น: friendly, professional, bold, playful)
|
||
```
|
||
|
||
#### 1.3 Design Context
|
||
```
|
||
8. มี brand guidelines/logo file ไหม?
|
||
9. มี reference sites ที่ชอบ/ไม่ชอบบ้างไหม? (ส่งลิงก์มาได้)
|
||
10. มีสีที่ต้องใช้/ห้ามใช้บ้างไหม?
|
||
```
|
||
|
||
#### 1.4 Technical Context
|
||
```
|
||
11. ต้องการหน้าอะไรบ้าง? (sitemap)
|
||
12. มี SMTP/email สำหรับส่งเมลไหม?
|
||
13. มี tracking tools ต้องติดตั้งไหม? (GA4, Facebook Pixel, etc.)
|
||
14. มี DPO หรือยัง? (สำหรับ PDPA)
|
||
```
|
||
|
||
---
|
||
|
||
### Phase 2: Creative Design (บังคับต้องทำ)
|
||
|
||
**เรียก skills: `ckm:design` + `ui-ux-pro-max` + `frontend-ui-engineering`**
|
||
|
||
#### 2.1 สร้าง Creative Brief
|
||
|
||
ก่อนสร้าง design ต้องมี creative brief ที่ชัดเจน:
|
||
|
||
```
|
||
# Creative Brief
|
||
|
||
## Brand Essence
|
||
- ชื่อ/บริษัท: [ชื่อ]
|
||
- สิ่งที่ทำ: [บริการ/สินค้า]
|
||
- ทำไมต่าง: [unique selling point]
|
||
|
||
## Target Emotion
|
||
- ต้องการให้คนเข้าเว็บแล้วรู้สึก: [เช่น มั่นใจ, สบายใจ, ตื่นเต้น, ไว้วางใจ]
|
||
|
||
## Design Direction
|
||
- ห้ามใช้: [สี/รูปแบบที่ไม่ชอบ]
|
||
- อาจใช้: [สี/รูปแบบที่ชอบ]
|
||
- References: [ลิงก์ที่ชอบ/ไม่ชอบ]
|
||
```
|
||
|
||
#### 2.2 สร้าง 2-3 Creative Directions ที่ต่างกันจริงๆ
|
||
|
||
**ใช้ `ckm:design` + `ui-ux-pro-max` สร้าง options ที่แตกต่างกัน:**
|
||
|
||
```
|
||
Direction A: "[Name]"
|
||
- Concept: [แนวคิดหลัก]
|
||
- Visual Style: [ลักษณะ visuals]
|
||
- Color Palette: [โทนสี]
|
||
- Typography: [แบบอักษร]
|
||
- Layout Character: [โครงสร้าง layout ที่เป็นเอกลักษณ์]
|
||
|
||
Direction B: "[Name]"
|
||
- Concept: [แนวคิดหลัก - ต่างจาก A]
|
||
- Visual Style: [ลักษณะ visuals - ต่างจาก A]
|
||
- Color Palette: [โทนสี - ต่างจาก A]
|
||
- Typography: [แบบอักษร - ต่างจาก A]
|
||
- Layout Character: [โครงสร้าง layout - ต่างจาก A]
|
||
```
|
||
|
||
#### 2.3 Present + Wait for Selection
|
||
|
||
**นำเสนอ directions ทั้งหมด แล้วรอ user เลือก**
|
||
|
||
---
|
||
|
||
### Phase 3: Master Plan (วางแผนทั้งหมด)
|
||
|
||
**เรียก skill: `spec-driven-development`**
|
||
|
||
สร้าง master plan ที่รวมทุกอย่าง:
|
||
|
||
```
|
||
# Master Plan: [ชื่อเว็บ]
|
||
|
||
## Selected Design Direction
|
||
[Direction ที่ user เลือกพร้อม rationale]
|
||
|
||
## Sitemap
|
||
/
|
||
├── home
|
||
├── about
|
||
├── services
|
||
├── contact
|
||
└── ...
|
||
|
||
## Design System
|
||
- Colors: [hex codes]
|
||
- Typography: [fonts + weights]
|
||
- Components: [list]
|
||
- Layout Patterns: [descriptions]
|
||
|
||
## Content Structure (Tina CMS)
|
||
- Collections: [posts, pages, etc.]
|
||
- Fields: [schema]
|
||
|
||
## Technical Stack
|
||
- Framework: Astro 6
|
||
- CMS: Tina CMS
|
||
- Styling: Tailwind CSS v4
|
||
- Consent: ConsentOS
|
||
|
||
## Tracking Scripts
|
||
- Analytics: [tools]
|
||
- Marketing: [tools]
|
||
|
||
## PDPA Compliance
|
||
- Privacy Policy
|
||
- Terms of Service
|
||
- ConsentOS Integration
|
||
|
||
## Development Phases
|
||
1. [Phase 1: Setup + Design Foundation]
|
||
2. [Phase 2: Build Pages]
|
||
3. [Phase 3: Content + QA]
|
||
4. [Phase 4: Deploy]
|
||
|
||
## Timeline
|
||
- Phase 1: X days
|
||
- Phase 2: X days
|
||
- Phase 3: X days
|
||
```
|
||
|
||
---
|
||
|
||
### ⏸️ APPROVAL GATE
|
||
|
||
**หยุดที่นี่ - รอ APPROVE ก่อนทำงาน**
|
||
|
||
แสดง:
|
||
1. Design direction ที่เลือก (screenshot/mockup)
|
||
2. Sitemap ที่จะสร้าง
|
||
3. Tech stack summary
|
||
4. Timeline estimate
|
||
|
||
**รอ user พิมพ์ "approve" หรือ "เริ่มได้" ก่อนไปต่อ**
|
||
|
||
---
|
||
|
||
### Phase 4: Execution (เริ่มทำหลัง APPROVE)
|
||
|
||
**หลังได้รับ approve แล้ว ทำตามแผนที่ approve โดยไม่ต้องถามต่อ**
|
||
|
||
#### Phase 4.1: Setup + Design Foundation
|
||
|
||
```bash
|
||
bash skills/website-creator/scripts/new-project.sh my-website
|
||
```
|
||
|
||
จากนั้น implement design system ที่ approve:
|
||
- Colors ใน Tailwind theme
|
||
- Typography
|
||
- Base components
|
||
- Layout patterns
|
||
|
||
#### Phase 4.2: Build Pages
|
||
|
||
Implement ทุก pages ตาม sitemap ที่ approve แล้ว
|
||
|
||
#### Phase 4.3: Content + Integration
|
||
|
||
- Tina CMS setup + content schema
|
||
- Legal pages (Privacy Policy, ToS)
|
||
- ConsentOS integration
|
||
- Tracking scripts
|
||
|
||
#### Phase 4.4: QA + Deploy
|
||
|
||
ตาม Step 9-10 ด้านล่าง
|
||
|
||
---
|
||
|
||
### Step 9: Preview + QA
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
**ก่อน QA — เรียก skills ตามลำดับ:**
|
||
|
||
1. **`code-review-and-quality`** — Full multi-axis code review ก่อน delivery
|
||
2. **`performance-optimization`** — Performance audit + fixes
|
||
3. **`browser-testing-with-devtools`** — ทดสอบใน real browser
|
||
|
||
**จากนั้นเรียก `dogfood` สำหรับ exploratory QA:**
|
||
|
||
```bash
|
||
/skill dogfood
|
||
"ทดสอบ user journey:
|
||
1. ดู home page → คลิก services
|
||
2. ดู about us
|
||
3. กรอก contact form
|
||
4. ทดสอบ consent popup (ConsentOS)
|
||
5. ตรวจ PDPA compliance (privacy policy, terms)
|
||
6. ตรวจ mobile responsive
|
||
7. ตรวจ SEO meta tags ทุกหน้า"
|
||
```
|
||
|
||
ให้ user ตรวจสอบ → รอ feedback → แก้ไข → รอ approve
|
||
|
||
---
|
||
|
||
### Step 10: Deploy
|
||
|
||
**เรียก skill: `easypanel-deploy` เมื่อ user ขอ**
|
||
|
||
```bash
|
||
/skill easypanel-deploy
|
||
"deploy ไปยัง easypanel server
|
||
server: openclaw-vps
|
||
project: my-website
|
||
domain: example.com
|
||
git repo: https://github.com/user/my-website"
|
||
```
|
||
|
||
---
|
||
|
||
### Step 4: Setup Astro + Tina CMS Project
|
||
|
||
**ใช้ script ที่มีอยู่แล้ว:**
|
||
|
||
```bash
|
||
# สร้าง project ใหม่จาก template
|
||
bash skills/website-creator/scripts/new-project.sh my-website
|
||
|
||
# หรือระบุ path
|
||
bash skills/website-creator/scripts/new-project.sh my-website /path/to/projects/
|
||
```
|
||
|
||
**Script ทำอะไร:**
|
||
1. Copy template `templates/astro-tina-starter/`
|
||
2. เพิ่ม PDPA consent system
|
||
3. Copy legal templates (privacy policy, terms)
|
||
4. ติดตั้ง dependencies
|
||
5. สร้าง .env file
|
||
6. Initialize git
|
||
|
||
**เปิด browser:**
|
||
- Frontend: http://localhost:4321 หรือ http://0.0.0.0:4321
|
||
- Tina Admin: http://localhost:4321/admin หรือ http://0.0.0.0:4321/admin (dev mode)
|
||
|
||
---
|
||
|
||
### Step 5: พัฒนา Components + Pages
|
||
|
||
**เรียก skills: `spec-driven-development` + `api-and-interface-design` + `ckm:design` + `ckm:ui-styling` + `frontend-ui-engineering`**
|
||
|
||
สร้างตาม sitemap ที่วางแผนไว้:
|
||
- FrontendLayout, Navigation, Footer
|
||
- Pages (Home, About, Services, Contact)
|
||
- Blog listing + detail pages
|
||
- Forms (Contact form ส่ง email จริง)
|
||
|
||
**สำคัญ — แยก Design Layer กับ Content Layer:**
|
||
|
||
Design skill (ui-ux-pro-max) ออกแบบ **หน้าตา + layout + animation** — ไม่ใช่ content structure
|
||
Tina CMS เก็บ **เนื้อหา (ข้อความ, format, links, images)** — ไม่ใช่ layout
|
||
|
||
ทั้งสองอยู่คนละ layer กัน → ต้องแยกทำ แล้วมารวมกันตอน integrate
|
||
|
||
---
|
||
|
||
### Step 5b: สร้างภาพประกอบด้วย `picture-it`
|
||
|
||
**เรียก skill: `picture-it`**
|
||
|
||
สำหรับทุก page/section ที่ต้องการ hero image, illustration หรือภาพประกอบ:
|
||
|
||
**วิธีใช้:**
|
||
|
||
```bash
|
||
# Load credentials ก่อน
|
||
set -a && source ~/.config/opencode/.env && set +a
|
||
export PATH="/home/kunthawat/snap/bun-js/87/.bun/bin:$PATH"
|
||
|
||
# ตรวจสอบ Thai font patch
|
||
bun ~/.hermes/skills/website-creator/creative/picture-it/scripts/thai-font-patch.ts --force
|
||
```
|
||
|
||
**Workflow สร้างภาพประกอบเว็บ:**
|
||
|
||
| Use Case | Pipeline | ค่าใช้จ่าย |
|
||
|----------|----------|-----------|
|
||
| Hero background | `generate flux-schnell` + `text` (Thai) + `grade cinematic` + `vignette` | ~$0.003 |
|
||
| Service illustration | `generate flux-schnell` + `remove-bg` (ถ้ามี product) + `compose` | ~$0.01 |
|
||
| Blog hero | `generate flux-schnell` + `edit seedream` (place logo) + `grade` | ~$0.043 |
|
||
| Social/OG image | `generate flux-schnell` + `text` + `grade` | ~$0.003 |
|
||
| Team/About photo | `generate flux-schnell` → realistic headshot style | ~$0.003 |
|
||
|
||
**ขนาดภาพแนะนำ:**
|
||
|
||
| Purpose | Size |
|
||
|---------|------|
|
||
| Hero banner | 1200×630 หรือ 1920×1080 |
|
||
| Blog hero | 1200×630 |
|
||
| OG Image (social share) | 1200×630 |
|
||
| Service card | 800×600 |
|
||
| Team member | 400×400 (circle crop) |
|
||
| Logo (ในภาพ) | 200×200 หรือเล็กกว่า |
|
||
|
||
**Workflow ตัวอย่าง — Hero Section:**
|
||
|
||
```bash
|
||
# 1. Generate background
|
||
picture-it generate \
|
||
--prompt "modern tech workspace, clean minimal, yellow #fed400 accent lighting" \
|
||
--size 1200x630 \
|
||
--model flux-schnell \
|
||
-o hero-bg.png
|
||
|
||
# 2. เพิ่ม Thai text
|
||
picture-it text \
|
||
-i hero-bg.png \
|
||
--title "บริการรับทำเว็บไซต์ SEO" \
|
||
--font "Kanit" \
|
||
--font-size 48 \
|
||
-o hero-texted.png
|
||
|
||
# 3. Color grade
|
||
picture-it grade -i hero-texted.png --name cinematic -o hero-final.png
|
||
```
|
||
|
||
**การบันทึกภาพไว้ใน project:**
|
||
|
||
```
|
||
src/
|
||
├── components/
|
||
│ └── Hero.astro # Hero component
|
||
└── assets/
|
||
├── heroes/ # Hero images
|
||
├── services/ # Service illustrations
|
||
├── blog/ # Blog heroes
|
||
└── og/ # Open Graph images
|
||
```
|
||
|
||
---
|
||
|
||
### Step 5c: Design + Tina Content Integration
|
||
|
||
**Design layer กับ Content layer แยกกัน — ค่อยรวมตอน build**
|
||
|
||
#### สิ่งที่ต้องเข้าใจ
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ ui-ux-pro-max / ckm:design — Design Layer │
|
||
│ • Component structure (Hero, Card, Navbar) │
|
||
│ • Color tokens, typography, spacing │
|
||
│ • Animation specs (150-300ms, ease-out) │
|
||
│ • Layout grid, responsive breakpoints │
|
||
│ • Interaction states (hover, press, disabled) │
|
||
│ Output: Astro + Tailwind code (component skeleton) │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Tina CMS — Content Layer │
|
||
│ • ข้อความ + format (bold, italic, link) │
|
||
│ • Headings (H1-H6) │
|
||
│ • Lists, blockquotes, code blocks │
|
||
│ • Images, links │
|
||
│ Output: MDX files (เนื้อหา) │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Integration — ครอบ Tina content ด้วย Design │
|
||
│ • Design component ครอบ MDX output │
|
||
│ • Animation class ที่ wrapper element │
|
||
│ • Design tokens apply ผ่าน Tailwind prose │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
#### ขั้นตอนที่ถูกต้อง
|
||
|
||
```
|
||
[1] Design Phase
|
||
ui-ux-pro-max → Component structure, tokens, animations
|
||
Output: Component skeleton (ไม่มี content)
|
||
↓
|
||
[2] Tina Phase
|
||
สร้าง Content Collections + MDX files
|
||
Output: Content structure ใน Tina (src/content/)
|
||
↓
|
||
[3] Content Phase
|
||
พิมพ์ content ใน Tina Admin (/admin)
|
||
Output: MDX files
|
||
↓
|
||
[4] Integration Phase
|
||
ครอบ Tina content ด้วย Design components
|
||
```
|
||
|
||
#### ตัวอย่าง: Page Structure (Design Output)
|
||
|
||
Design skill อาจให้ component แบบนี้:
|
||
|
||
```astro
|
||
---
|
||
// ❌ สิ่งที่ design skill อาจให้มา — hardcode content
|
||
---
|
||
|
||
<div class="hero-section">
|
||
<h1>Welcome to Our Site</h1> <!-- hardcode -->
|
||
<p class="hero-desc">Amazing content here...</p> <!-- hardcode -->
|
||
</div>
|
||
```
|
||
|
||
ต้องแปลงเป็น:
|
||
|
||
```astro
|
||
---
|
||
// ✅ ครอบ Tina content ด้วย design component
|
||
import { Container, Heading, Prose } from '@/components/ui';
|
||
|
||
interface Props {
|
||
title: string;
|
||
body: string; // จาก MDX frontmatter หรือ Tina query
|
||
}
|
||
|
||
const { title, body } = Astro.props;
|
||
---
|
||
|
||
<Container class="py-20">
|
||
<Heading level={1} class="text-5xl font-bold mb-6">{title}</Heading>
|
||
{body && (
|
||
<Prose>
|
||
<slot /> <!-- MDX content จะมาอยู่ตรงนี้ -->
|
||
</Prose>
|
||
)}
|
||
</Container>
|
||
```
|
||
|
||
#### Tina Content Collections
|
||
|
||
กำหนดว่า content แต่ส่วนเก็บใน collection ไหน:
|
||
|
||
```typescript
|
||
// .tina/schema.ts
|
||
const schema = defineSchema({
|
||
collections: [
|
||
{
|
||
name: 'post',
|
||
label: 'Posts',
|
||
path: 'src/content/posts',
|
||
fields: [
|
||
{ type: 'string', name: 'title', label: 'Title', required: true },
|
||
{ type: 'string', name: 'slug', label: 'Slug', required: true },
|
||
{ type: 'string', name: 'description', label: 'Description' },
|
||
{ type: 'datetime', name: 'publishedAt', label: 'Published At' },
|
||
{ type: 'rich-text', name: 'body', label: 'Body', isBody: true },
|
||
],
|
||
},
|
||
{
|
||
name: 'page',
|
||
label: 'Pages',
|
||
path: 'src/content/pages',
|
||
fields: [
|
||
{ type: 'string', name: 'title', label: 'Title', required: true },
|
||
{ type: 'string', name: 'slug', label: 'Slug', required: true },
|
||
{ type: 'rich-text', name: 'body', label: 'Body', isBody: true },
|
||
],
|
||
},
|
||
{
|
||
name: 'settings',
|
||
label: 'Settings',
|
||
path: 'src/content/settings',
|
||
format: 'json',
|
||
fields: [
|
||
{ type: 'string', name: 'siteName', label: 'Site Name' },
|
||
{ type: 'string', name: 'siteDescription', label: 'Description' },
|
||
],
|
||
},
|
||
],
|
||
})
|
||
```
|
||
|
||
#### วิธี Integrate: Design Components + Tina Content
|
||
|
||
```astro
|
||
---
|
||
// src/pages/blog/[slug].astro
|
||
import Layout from '@/layouts/Layout.astro';
|
||
import { Container, Heading, Prose } from '@/components/ui';
|
||
|
||
// Astro ดึง content จาก MDX files
|
||
const { slug } = Astro.params;
|
||
|
||
// ด้วย Astro content collections
|
||
const { post } = Astro.props;
|
||
---
|
||
|
||
<Layout title={post.data.title} description={post.data.description}>
|
||
<Container class="py-20">
|
||
<Heading level={1} class="text-5xl font-bold mb-6">
|
||
{post.data.title}
|
||
</Heading>
|
||
|
||
{post.data.description && (
|
||
<p class="text-xl text-gray-600 mb-8">{post.data.description}</p>
|
||
)}
|
||
|
||
<Prose>
|
||
<!-- MDX content จะ render ตรงนี้ -->
|
||
<slot />
|
||
</Prose>
|
||
</Container>
|
||
</Layout>
|
||
```
|
||
|
||
---
|
||
|
||
### Step 7: PDPA Compliance
|
||
|
||
**ใช้ templates ที่มีอยู่แล้ว:**
|
||
|
||
1. **Privacy Policy** — ใช้ `templates/privacy-policy.md`
|
||
- ภาษากฎหมาย PDPA ครบถ้วน
|
||
- แทนที่ placeholders ด้วยข้อมูลจริง
|
||
|
||
2. **Terms of Service** — ใช้ `templates/terms-of-service.md`
|
||
|
||
3. **ConsentOS + Tracking Scripts** — ใช้ `src/components/TrackingScripts.astro`
|
||
|
||
**Template มี TrackingScripts.astro ที่รองรับ:**
|
||
|
||
| Category | Script | ENV Variable |
|
||
|----------|--------|-------------|
|
||
| Analytics | Google Analytics 4 | `PUBLIC_GA4_ID` |
|
||
| Analytics | Google Tag Manager | `PUBLIC_GTM_ID` |
|
||
| Analytics | Umami | `PUBLIC_UMAMI_URL`, `PUBLIC_UMAMI_WEBSITE_ID` |
|
||
| Analytics | Microsoft Clarity | `PUBLIC_CLARITY_ID` |
|
||
| Marketing | Facebook Pixel | `PUBLIC_FB_PIXEL_ID` |
|
||
| Marketing | Google Ads | `PUBLIC_GOOGLE_ADS_ID` |
|
||
| Marketing | TikTok Pixel | `PUBLIC_TIKTOK_PIXEL_ID` |
|
||
| Marketing | LINE Channel Tag | `PUBLIC_LINE_CHANNEL_ID` |
|
||
|
||
**Environment Variables:**
|
||
|
||
```bash
|
||
# ConsentOS
|
||
PUBLIC_CONSENT_SITE_ID=your-consent-site-id
|
||
PUBLIC_CONSENT_API_BASE=https://consent.moreminimore.com
|
||
|
||
# Analytics
|
||
PUBLIC_GA4_ID=G-XXXXXXXXXX
|
||
PUBLIC_GTM_ID=GTM-XXXXXXX
|
||
PUBLIC_UMAMI_URL=https://umami.example.com
|
||
PUBLIC_UMAMI_WEBSITE_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||
PUBLIC_CLARITY_ID=xxxxxxxxxx
|
||
|
||
# Marketing
|
||
PUBLIC_FB_PIXEL_ID=123456789
|
||
PUBLIC_GOOGLE_ADS_ID=AW-123456789
|
||
PUBLIC_TIKTOK_PIXEL_ID=XXXXXXXX
|
||
PUBLIC_LINE_CHANNEL_ID=1234567890
|
||
```
|
||
|
||
**Tracking Flow:**
|
||
|
||
```
|
||
TrackingScripts.astro (data-consent-category attributes)
|
||
↓
|
||
ConsentOS consent-loader.js (scan + auto-block)
|
||
↓
|
||
Scripts execute only after user consent
|
||
```
|
||
|
||
**Consent Categories:**
|
||
- **Analytics** — GA4, GTM, Umami, Clarity
|
||
- **Marketing** — Facebook Pixel, TikTok, LINE, Google Ads
|
||
|
||
**Right to be Forgotten:**
|
||
- ConsentOS มี API สำหรับลบข้อมูล user
|
||
|
||
---
|
||
|
||
### Step 8: SEO Setup
|
||
|
||
**เรียก skills: `seo-analyzers` + `seo-geo` + `seo-multi-channel`**
|
||
|
||
1. **Meta tags ทุกหน้า** — ใช้ frontmatter จาก MDX หรือ static
|
||
2. **sitemap.xml** — Astro ใช้ `@astrojs/sitemap`
|
||
3. **robots.txt**
|
||
4. **Open Graph images** — **ใช้ `picture-it` สร้าง OG image template ที่ consistent**
|
||
5. **JSON-LD structured data**
|
||
6. **Thai language optimization**
|
||
|
||
```bash
|
||
# ติดตั้ง sitemap
|
||
npx astro add sitemap
|
||
```
|
||
|
||
```javascript
|
||
// astro.config.mjs
|
||
import sitemap from '@astrojs/sitemap';
|
||
|
||
export default defineConfig({
|
||
site: 'https://example.com',
|
||
integrations: [sitemap(), tina()],
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
### Step 9: Preview + QA
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
**ก่อน QA — เรียก skills ตามลำดับ:**
|
||
|
||
1. **`code-review-and-quality`** — Full multi-axis code review ก่อน delivery
|
||
2. **`performance-optimization`** — Performance audit + fixes
|
||
3. **`browser-testing-with-devtools`** — ทดสอบใน real browser
|
||
|
||
**จากนั้นเรียก `dogfood` สำหรับ exploratory QA:**
|
||
|
||
```bash
|
||
/skill dogfood
|
||
"ทดสอบ user journey:
|
||
1. ดู home page → คลิก services
|
||
2. ดู about us
|
||
3. กรอก contact form
|
||
4. ทดสอบ consent popup (ConsentOS)
|
||
5. ตรวจ PDPA compliance (privacy policy, terms)
|
||
6. ตรวจ mobile responsive
|
||
7. ตรวจ SEO meta tags ทุกหน้า"
|
||
```
|
||
|
||
ให้ user ตรวจสอบ → รอ feedback → แก้ไข → รอ approve
|
||
|
||
---
|
||
|
||
### Step 10: Deploy
|
||
|
||
**เรียก skill: `easypanel-deploy`**
|
||
|
||
```bash
|
||
/skill easypanel-deploy
|
||
"deploy ไปยัง easypanel server
|
||
server: openclaw-vps
|
||
project: my-website
|
||
domain: example.com
|
||
git repo: https://github.com/user/my-website"
|
||
```
|
||
|
||
---
|
||
|
||
## Workflow B: ปรับปรุงเว็บที่มีอยู่แล้ว (Existing Repo)
|
||
|
||
### ความหมายของ "Existing Repo"
|
||
|
||
Repo ที่มีโครงสร้าง Astro + Tina แล้ว แต่ยังไม่สมบูรณ์ — เช่น:
|
||
- มี starter template แต่ไม่มี content
|
||
- มี design tokens แล้วแต่ยังไม่มี pages
|
||
- มีบางหน้าแต่ต้องการปรับปรุงเนื้อหา/design
|
||
|
||
**ไม่ใช่** 新规 creation — มี codebase อยู่แล้ว ปรับในที่เดิม
|
||
|
||
---
|
||
|
||
### ขั้นตอน
|
||
|
||
```
|
||
[1] ตรวจสอบ repo ที่มี (terminal/find ดูโครงสร้าง)
|
||
│
|
||
[2] สำรวจ: astro.config.mjs, components, pages, design tokens
|
||
│
|
||
[3] สำรวจ content ที่มี (Posts, Pages จากเว็บเดิม) → วางแผน Migration
|
||
│
|
||
[4] Migrate content เข้า Tina CMS
|
||
│
|
||
[5] ตรวจสอบ /admin ว่าเห็น Posts + Pages พร้อมแก้ไขได้
|
||
│
|
||
[6] Integrate: อัปเดต Pages ให้อ่านจาก Tina แทน hardcode
|
||
│ (ดู **Design + Tina Integration** ด้านบน)
|
||
│
|
||
[7] สรุปสิ่งที่มี vs สิ่งที่ขาด → แผน Sitemap
|
||
│
|
||
[8] ถามคำถามที่ขาด (content, portfolio, pricing, dark/light)
|
||
│
|
||
[9] รอ approve
|
||
↓
|
||
จากนั้น → Workflow A Step 3 เป็นต้นไป (พัฒนา Components + Pages)
|
||
```
|
||
|
||
---
|
||
|
||
## Migration: Next.js + Payload → Astro + Tina
|
||
|
||
**ใช้ script ที่มีอยู่แล้ว:**
|
||
|
||
```bash
|
||
# Migrate existing website ไป Astro + Tina
|
||
bash skills/website-creator/scripts/migrate-tina.sh /path/to/existing-site /path/to/migrated-site
|
||
```
|
||
|
||
**Script ทำอะไร:**
|
||
1. Detect source technology (Astro, Next.js, Remix, etc.)
|
||
2. Analyze source content
|
||
3. Copy Astro+Tina template
|
||
4. Migrate content (MD/MDX files)
|
||
5. Add PDPA consent system
|
||
6. Create Tina schema
|
||
7. Generate migration report
|
||
|
||
### Content Migration Checklist
|
||
|
||
| จาก Payload | ไป Tina |
|
||
|------------|---------|
|
||
| `payload.find()` | Astro content collections |
|
||
| `RichText` component | MDX files |
|
||
| `payload.config.ts` collections | `.tina/schema.ts` collections |
|
||
| MongoDB/PostgreSQL | ConsentOS (external) |
|
||
| `/admin` | `/admin` (Tina visual editor) |
|
||
| Payload Auth | Tina Auth (optional) |
|
||
|
||
---
|
||
|
||
## Astro Content Collections
|
||
|
||
Astro ใช้ content collections สำหรับ type-safe content management:
|
||
|
||
### สร้าง Collection
|
||
|
||
```typescript
|
||
// src/content/config.ts
|
||
import { defineCollection, z } from 'astro:content';
|
||
|
||
const postsCollection = defineCollection({
|
||
type: 'content',
|
||
schema: z.object({
|
||
title: z.string(),
|
||
description: z.string().optional(),
|
||
publishedAt: z.date().optional(),
|
||
author: z.string().optional(),
|
||
image: z.string().optional(),
|
||
}),
|
||
});
|
||
|
||
const pagesCollection = defineCollection({
|
||
type: 'content',
|
||
schema: z.object({
|
||
title: z.string(),
|
||
description: z.string().optional(),
|
||
}),
|
||
});
|
||
|
||
export const collections = {
|
||
posts: postsCollection,
|
||
pages: pagesCollection,
|
||
};
|
||
```
|
||
|
||
### ใช้ Collection
|
||
|
||
```astro
|
||
---
|
||
// src/pages/blog/[slug].astro
|
||
import { getCollection } from 'astro:content';
|
||
|
||
export async function getStaticPaths() {
|
||
const posts = await getCollection('posts');
|
||
return posts.map((post) => ({
|
||
params: { slug: post.slug },
|
||
props: { post },
|
||
}));
|
||
}
|
||
|
||
const { post } = Astro.props;
|
||
const { Content } = await post.render();
|
||
---
|
||
|
||
<article>
|
||
<h1>{post.data.title}</h1>
|
||
<Content />
|
||
</article>
|
||
```
|
||
|
||
---
|
||
|
||
## Tina CMS Integration
|
||
|
||
### Local Development
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
Tina จะ available ที่ `http://localhost:4321/admin` หรือ `http://0.0.0.0:4321/admin`
|
||
|
||
### Production Setup
|
||
|
||
```bash
|
||
# รัน script สำหรับติดตั้ง Tina backend
|
||
bash scripts/install-tina-backend.sh
|
||
```
|
||
|
||
**ต้องมี:**
|
||
- `TINA_TOKEN` — Production authentication token
|
||
- `TINA_CLIENT_ID` — Tina client ID
|
||
|
||
### Tina Schema Best Practices
|
||
|
||
```typescript
|
||
// .tina/schema.ts
|
||
const schema = defineSchema({
|
||
collections: [
|
||
{
|
||
name: 'post',
|
||
label: 'Blog Posts',
|
||
path: 'src/content/posts',
|
||
fields: [
|
||
{
|
||
type: 'string',
|
||
name: 'title',
|
||
label: 'Title',
|
||
isTitle: true, // ใช้เป็น title ใน admin UI
|
||
required: true,
|
||
},
|
||
{
|
||
type: 'string',
|
||
name: 'slug',
|
||
label: 'URL Slug',
|
||
required: true,
|
||
},
|
||
{
|
||
type: 'datetime',
|
||
name: 'publishedAt',
|
||
label: 'Publish Date',
|
||
},
|
||
{
|
||
type: 'rich-text',
|
||
name: 'body',
|
||
label: 'Content',
|
||
isBody: true, // เป็น body หลัก
|
||
},
|
||
],
|
||
},
|
||
],
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
## Templates
|
||
|
||
### Astro Tina Starter (`templates/astro-tina-starter/`)
|
||
|
||
Base template ที่รวมทุกอย่างพร้อม:
|
||
|
||
```
|
||
astro-tina-starter/
|
||
├── .tina/
|
||
│ ├── config.ts # Tina CMS configuration
|
||
│ └── schema.ts # Content schema definitions
|
||
├── src/
|
||
│ ├── styles/
|
||
│ │ └── global.css # Tailwind v4 styles + @theme
|
||
│ ├── layouts/
|
||
│ │ └── Layout.astro
|
||
│ ├── pages/
|
||
│ │ └── index.astro
|
||
│ ├── components/
|
||
│ │ └── Header.astro
|
||
│ └── content/
|
||
│ ├── config.ts # Astro content collections
|
||
│ ├── posts/ # Blog posts (MDX)
|
||
│ ├── pages/ # Static pages (MDX)
|
||
│ └── settings/ # Site settings (JSON)
|
||
├── public/
|
||
│ └── favicon.svg
|
||
├── Dockerfile
|
||
├── astro.config.mjs
|
||
├── tsconfig.json
|
||
└── package.json
|
||
```
|
||
|
||
**Features ที่มี:**
|
||
- Astro 6.1.7 + Tina CMS 2.x
|
||
- Tailwind CSS 4.x with `@tailwindcss/vite`
|
||
- Thai language support
|
||
- Docker-ready
|
||
- External consent system integration
|
||
|
||
---
|
||
|
||
## Docker
|
||
|
||
### Development
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
### Production (Multi-stage Dockerfile)
|
||
|
||
```dockerfile
|
||
FROM node:22-alpine AS deps
|
||
RUN corepack enable && corepack prepare pnpm@9.0.0 --activate
|
||
WORKDIR /app
|
||
COPY package.json pnpm-lock.yaml* ./
|
||
RUN pnpm install --frozen-lockfile
|
||
|
||
FROM deps AS builder
|
||
COPY . .
|
||
RUN pnpm build
|
||
|
||
FROM node:22-alpine AS runner
|
||
WORKDIR /app
|
||
ENV NODE_ENV production
|
||
RUN adduser --system --uid 1001 astro
|
||
USER astro
|
||
EXPOSE 8080
|
||
CMD ["node", "dist/server/entry.mjs"]
|
||
```
|
||
|
||
**Build command:**
|
||
```bash
|
||
npm run build
|
||
```
|
||
|
||
---
|
||
|
||
## Sub-skill Routing
|
||
|
||
| ขั้นตอน | Sub-skill | รายละเอียด |
|
||
|---------|-----------|-------------|
|
||
| **ตลอด workflow** | `spec-driven-development` | เขียน spec ก่อน implement ทุกครั้ง |
|
||
| Design Framework | `ckm:design` | Brand, tokens, design system |
|
||
| Design Framework | `frontend-ui-engineering` | UI component architecture, patterns |
|
||
| UI Components | `ckm:ui-styling` | shadcn/ui, Tailwind CSS |
|
||
| UI/UX Design | `ui-ux-pro-max` | Wireframes, mockups, 50+ design patterns |
|
||
| Brand Identity | `brand` | Logo, colors, typography, voice |
|
||
| Banner/Hero Images | `banner-design` | Social, ads, web heroes |
|
||
| Develop Components + Pages | `api-and-interface-design` | API design, component interfaces |
|
||
| Before QA | `code-review-and-quality` | Full multi-axis code review |
|
||
| Before QA | `performance-optimization` | Performance audit + fixes |
|
||
| QA Testing | `browser-testing-with-devtools` | Real browser testing |
|
||
| QA Testing | `dogfood` | Exploratory QA of web app |
|
||
| SEO Planning | `seo-context` | Per-project SEO context |
|
||
| SEO Audit | `seo-analyzers` | Thai language SEO analysis |
|
||
| GEO (AI Search) | `seo-geo` | AI Overviews, llms.txt, crawler |
|
||
| Multi-channel Content | `seo-multi-channel` | Facebook, LinkedIn, blog content |
|
||
| Deploy | `easypanel-deploy` | Easypanel hosting |
|
||
| Design + Tina Integration | `frontend-ui-engineering` | แยก design layer กับ content layer |
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
### Build fails: "Cannot find module '@tailwindcss/vite'"
|
||
|
||
**Error:** `Cannot find module '@tailwindcss/vite'`
|
||
|
||
**ทางแก้:**
|
||
|
||
```bash
|
||
# ติดตั้ง @tailwindcss/vite
|
||
npm install -D @tailwindcss/vite
|
||
|
||
# หรือถ้าใช้ Tailwind v3 syntax อยู่ → ต้องเปลี่ยนเป็น v4
|
||
# ใน global.css:
|
||
@import "tailwindcss"; # ไม่ใช่ @tailwind base; @tailwind components; @tailwind utilities;
|
||
```
|
||
|
||
### Tina Admin not loading
|
||
|
||
**อาการ:** `/admin` แสดง blank page หรือ error
|
||
|
||
**ทางแก้:**
|
||
|
||
1. ตรวจสอบว่า Tina config ถูกต้อง:
|
||
```javascript
|
||
// astro.config.mjs
|
||
import tina from 'tinacms';
|
||
|
||
export default defineConfig({
|
||
integrations: [tina()],
|
||
});
|
||
```
|
||
|
||
2. ตรวจสอบว่า `.tina/schema.ts` มีอยู่
|
||
|
||
3. ลองรัน `npm run dev` ใหม่
|
||
|
||
### Port already in use
|
||
|
||
**Error:** `Port 4321 is already in use`
|
||
|
||
**ทางแก้:**
|
||
|
||
```bash
|
||
# หา process ที่ใช้ port
|
||
lsof -i :4321
|
||
|
||
# kill process
|
||
kill <PID>
|
||
|
||
# หรือรัน port อื่น
|
||
npm run dev -- --port 4322
|
||
```
|
||
|
||
### MDX content not rendering
|
||
|
||
**อาการ:** MDX files ไม่แสดง content
|
||
|
||
**ทางแก้:**
|
||
|
||
```astro
|
||
---
|
||
// ต้องใช้ .render() เพื่อดึง Content component
|
||
const { Content } = await post.render();
|
||
---
|
||
|
||
<Content />
|
||
```
|
||
|
||
---
|
||
|
||
## Key Principles
|
||
|
||
1. **Plan-First Approach**
|
||
- แสดงแผนก่อนลงมือเสมอ
|
||
- รอ user approve ก่อน
|
||
|
||
2. **Astro Latest**
|
||
- ใช้ Astro 6.x เวอร์ชั่นล่าสุด
|
||
- Tina CMS สำหรับ content management
|
||
|
||
3. **Thai-First**
|
||
- ภาษาไทยเป็นหลัก
|
||
- Thai fonts (Kanit, Noto Sans Thai)
|
||
- Thai typography CSS
|
||
- Thai structured data (LocalBusiness, Organization)
|
||
|
||
4. **Preview Before Deploy**
|
||
- Preview ผ่าน local dev server ที่ `0.0.0.0`
|
||
- ให้ user ตรวจสอบก่อน deploy
|
||
|
||
5. **Tailwind v4**
|
||
- ใช้ `@tailwindcss/vite` plugin
|
||
- ใช้ `@theme` block แทน tailwind.config.js
|
||
- ไม่ใช้ `@astrojs/tailwind` (deprecated)
|