--- 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, astro-db, 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 - **Astro DB** — Built-in database (libSQL) สำหรับ consent logs และ dynamic content - **Tailwind CSS 4.x** — ใช้ `@tailwindcss/vite` plugin **Pattern อ้างอิง:** ใช้ template ที่มีอยู่แล้ว: `templates/astro-tina-starter/` ### Astro Project Structure ``` src/ ├── components/ # Astro/React components │ └── consent/ # PDPA consent system ├── 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 ├── stores/ # Nano Stores (client state) ├── styles/ │ └── global.css # Tailwind v4 + @theme ├── db/ │ └── config.ts # Astro DB schema └── 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:** ใช้ `output: 'server'` สำหรับ dynamic pages - Astro มี hybrid mode — บางหน้า static บางหน้า dynamic ## 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', server: { port: 4321, }, }) ``` ### 2. Required Dependencies ```json { "dependencies": { "astro": "^6.1.7", "@tinacms/cli": "^2.1.0", "tinacms": "^2.2.0", "@astrojs/db": "^0.14.0", "nanostores": "^0.11.0", "@nanostores/preact": "^0.5.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: สร้างเว็บใหม่ ### Step 1: Pre-Project Questions ใช้ `references/questions.md` เป็นแนวทาง: ``` 1. ชื่อเว็บไซต์/บริษัท? 2. ทำอะไร? (ขายอะไร/ให้บริการอะไร) 3. กลุ่มเป้าหมายคือใคร? 4. มีเว็บอยู่แล้วหรือยัง? 5. ชอบสี/ดีไซน์แบบไหน? 6. มี logo file ไหม? 7. ต้องการหน้าอะไรบ้าง? 8. มี SMTP/email สำหรับส่งเมลไหม? 9. มี GA4/Marketing tools ไหม? 10. มี DPO หรือยัง? ``` --- ### Step 2: Plan Sitemap + Content Structure **เรียก skill: `spec-driven-development`** — เขียน SPEC.md ก่อนลงมือทุกครั้ง แสดง sitemap ให้ user ดูก่อนเสมอ รอ approve ก่อนลงมือ: ``` / # Home /about # About Us /services # Services overview /contact # Contact + Form /blog # Blog listing (ถ้ามี) /blog/[slug] # Individual blog post /privacy-policy # PDPA Privacy Policy /terms-of-service # PDPA Terms of Service ``` --- ### Step 3: Design Framework **เรียก skills: `ckm:design` + `frontend-ui-engineering` + `ckm:ui-styling` + `ui-ux-pro-max`** ขั้นตอน: 1. ถามว่ามี brand guidelines หรือ reference ไหม 2. ถ้าไม่มี → ถาม 2 คำถาม: - ชอบ dark mode ไหม หรือ light mode อย่างเดียว? - ชอบ style แบบไหน: minimal, bold, creative? 3. ใช้ `ckm:design` เพื่อสร้าง design system 4. ใช้ `ui-ux-pro-max` เพื่อออกแบบ wireframes 5. ใช้ `ckm:ui-styling` เพื่อสร้าง components --- ### 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 - Tina Admin: http://localhost: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 ---

Welcome to Our Site

Amazing content here...

``` ต้องแปลงเป็น: ```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; --- {title} {body && ( )} ``` #### 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; --- {post.data.title} {post.data.description && (

{post.data.description}

)}
``` --- ### Step 7: PDPA Compliance **ใช้ templates ที่มีอยู่แล้ว:** 1. **Privacy Policy** — ใช้ `templates/privacy-policy.md` - ภาษากฎหมาย PDPA ครบถ้วน - แทนที่ placeholders ด้วยข้อมูลจริง 2. **Terms of Service** — ใช้ `templates/terms-of-service.md` 3. **PDPA Topics ที่ต้องครอบคลุม:** **3.1 Cookie Consent Popup** - ไม่ block content - Options: Accept All, Reject All, Customize - ถ้า reject → ไม่ load GA4/marketing scripts **3.2 Consent Logging (PDPA)** - เก็บ log ลง Astro DB (ไม่ต้อง MongoDB ภายนอก) - ระบุ: action, purpose, analytics/marketing/functional flags, ip, userAgent, timestamp **ไฟล์ที่ต้องสร้าง:** 1. **`ConsentBanner.astro`** — Consent banner component (มีใน template) ```astro --- // src/components/consent/ConsentBanner.astro import { consentStore } from '@/stores/consent'; --- ``` 2. **`db/config.ts`** — Astro DB schema: ```typescript // src/db/config.ts import { defineDb, column } from 'astro:db'; export const ConsentLog = defineTable({ columns: { id: column serial({ 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({ default: { now: true } }), sessionId: column text({ optional: true }), }, }); ``` 3. **`src/pages/api/consent.ts`** — API endpoint: ```typescript // src/pages/api/consent.ts import type { APIRoute } from 'astro'; import { db, ConsentLog } from 'astro:db'; export const POST: APIRoute = async ({ request }) => { const body = await request.json(); const { action, purpose, analytics, marketing, functional } = body; const ip = request.headers.get('x-forwarded-for')?.split(',')[0] || 'unknown'; const userAgent = request.headers.get('user-agent') || 'unknown'; await db.insert(ConsentLog).values({ action, purpose, analytics, marketing, functional, userAgent, ip, }); return new Response(JSON.stringify({ success: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; ``` 4. **เพิ่มใน astro.config.mjs:** ```javascript // astro.config.mjs import { defineConfig } from 'astro/config'; import tailwindcss from '@tailwindcss/vite'; import tina from 'tinacms'; export default defineConfig({ integrations: [tina()], vite: { plugins: [tailwindcss()] }, output: 'static', // Astro DB รวมอยู่แล้ว ไม่ต้องติดตั้งเพิ่ม }); ``` **3.3 Right to be Forgotten** - API endpoint สำหรับลบข้อมูล 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. ทดสอบ cookie consent popup 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 | Astro DB (built-in) | | `/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(); ---

{post.data.title}

``` --- ## Tina CMS Integration ### Local Development ```bash npm run dev ``` Tina จะ available ที่ `http://localhost: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 ├── db/ │ ├── config.ts # Astro DB schema │ └── seed.ts # Database seed script ├── 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` - Astro DB for consent logging - Nano Stores for client state - Thai language support - Docker-ready ### PDPA Consent Template (`templates/consent/`) Template สำหรับ PDPA consent system: ``` consent/ ├── ConsentBanner.astro # Consent banner component ├── api/ │ ├── consent.ts # API endpoints │ └── route.ts # Astro API route ├── db/ │ └── config.ts # Astro DB ConsentLog table └── stores/ └── consent.ts # Nano Stores ``` --- ## 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; ``` ### Astro DB not working **Error:** `Cannot find module 'astro:db'` หรือ tables not found **ทางแก้:** ```bash # Push schema to database npm run db:push # ตรวจสอบว่ามี astro:db import ถูกต้อง import { db, ConsentLog } from 'astro:db'; ``` ### 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 # หรือรัน port อื่น npm run dev -- --port 4322 ``` ### MDX content not rendering **อาการ:** MDX files ไม่แสดง content **ทางแก้:** ```astro --- // ต้องใช้ .render() เพื่อดึง Content component const { Content } = await post.render(); --- ``` ### Static build vs SSR **อาการ:** API routes ไม่ทำงานหลัง build **ทางแก้:** ถ้าต้องการใช้ API routes (เช่น consent API): ```javascript // astro.config.mjs export default defineConfig({ output: 'hybrid', // หรือ 'server' สำหรับทุกหน้า dynamic }); ``` แล้วเพิ่ม `export const prerender = false;` ใน API route files. --- ## 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)