Update skills: add website-creator, mql-developer, ecommerce-astro
Changes: - Add FAL_KEY and GEMINI_API_KEY to .env.example - Update picture-it to use ~/.config/opencode/.env (unified creds) - Remove shodh-memory skill (no longer used) - Remove alphaear-* skills (deprecated) - Remove thai-frontend-dev skill (replaced by website-creator) - Remove theme-factory skill - Add mql-developer skill (MQL5 trading) - Add ecommerce-astro skill (Astro e-commerce) - Add website-creator skill (Next.js + Payload CMS) - Update install script for new skills
This commit is contained in:
488
skills/website-creator/references/payload-nextjs-notes.md
Normal file
488
skills/website-creator/references/payload-nextjs-notes.md
Normal file
@@ -0,0 +1,488 @@
|
||||
# Payload CMS + Next.js Troubleshooting
|
||||
|
||||
## PostgreSQL Connection Issues
|
||||
|
||||
### Wrong port
|
||||
- Docker container `astro-starter-db-1` exposes PostgreSQL on port **5555** (not 5432)
|
||||
- Fix: Use `localhost:5555` in DATABASE_URL for local development
|
||||
|
||||
### Wrong database name
|
||||
- Payload CMS expects database `payload` (matches `POSTGRES_DB=payload`)
|
||||
- **NOT** `postgres` or `payloaddb`
|
||||
- Working DATABASE_URL: `postgresql://payload:payloadpass@localhost:5555/payload`
|
||||
|
||||
### Wrong credentials
|
||||
- Docker compose uses `POSTGRES_USER=payload` / `POSTGRES_PASSWORD=payloadpass`
|
||||
- NOT the default `postgres:postgres`
|
||||
|
||||
### Schema not creating tables
|
||||
**Symptom:** Admin page shows blank/white but HTML loads fine. Tables don't exist in DB.
|
||||
|
||||
**Root cause:** `payload migrate` may not have run or failed silently.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# 1. Stop dev server
|
||||
pkill -f "next"
|
||||
|
||||
# 2. Run migration
|
||||
cd /path/to/project
|
||||
pnpm payload migrate --yes
|
||||
# OR for fresh start:
|
||||
pnpm payload migrate:fresh --yes
|
||||
|
||||
# 3. Verify tables created
|
||||
PGPASSWORD=payloadpass psql -h localhost -p 5555 -U payload -d payload -c "\dt"
|
||||
|
||||
# 4. Restart dev server
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## Admin Page Blank/White Screen
|
||||
|
||||
### Causes
|
||||
|
||||
1. **Browser cache from old deployment** — standalone mode serves old static file hashes
|
||||
- Fix: Ctrl+Shift+R (hard refresh) or open Incognito window
|
||||
|
||||
2. **Static files not matching the build** — running standalone with dev `.next`
|
||||
- Fix: Always `pnpm build` before running `node .next/standalone/server.js`
|
||||
- OR just use `pnpm dev` for development
|
||||
|
||||
3. **Database tables don't exist** — Payload admin can't load without schema
|
||||
- Fix: Run `pnpm payload migrate` to create tables
|
||||
|
||||
4. **WebSocket HMR errors** — not a real issue, just hot reload failing
|
||||
- This is cosmetic and doesn't affect functionality
|
||||
|
||||
### Verification
|
||||
```bash
|
||||
# Check if admin HTML loads
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/admin
|
||||
# Should return 200
|
||||
|
||||
# Check if JS chunks load (may 404 in dev mode - OK)
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/_next/static/chunks/0pmuyajd0waqg.js
|
||||
|
||||
# Check DB tables
|
||||
PGPASSWORD=payloadpass psql -h localhost -p 5555 -U payload -d payload -c "\dt"
|
||||
# Should show: media, payload_kv, posts, users, users_sessions, etc.
|
||||
```
|
||||
|
||||
## Payload Migration Commands
|
||||
|
||||
```bash
|
||||
pnpm payload migrate # Run pending migrations
|
||||
pnpm payload migrate:fresh # Drop all tables and recreate (DANGEROUS)
|
||||
pnpm payload migrate:reset # Reset migration history
|
||||
pnpm generate:types # Generate TypeScript types
|
||||
pnpm generate:importmap # Regenerate import map
|
||||
```
|
||||
|
||||
## Payload CMS 3.x Breaking Changes
|
||||
|
||||
- `GRAPHQL_GET` → use `GRAPHQL_PLAYGROUND_GET` from `@payloadcms/next/routes`
|
||||
- Collection config imports must use `import type { CollectionConfig } from 'payload'`
|
||||
- `payload push` deprecated → use `payload migrate`
|
||||
- PostgreSQL adapter in separate package: `@payloadcms/db-postgres`
|
||||
- Rich text editor in separate package: `@payloadcms/richtext-lexical`
|
||||
|
||||
## Docker Compose for PostgreSQL
|
||||
|
||||
```yaml
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: payload
|
||||
POSTGRES_PASSWORD: payloadpass
|
||||
POSTGRES_DB: payload
|
||||
ports:
|
||||
- '5432:5432' # Only if not already in use
|
||||
```
|
||||
|
||||
DATABASE_URL: `postgresql://payload:***@localhost:5432/payload`
|
||||
(Port depends on what's already mapped in docker-compose)
|
||||
|
||||
---
|
||||
|
||||
## Next.js 15.3.8 + React 19 SWC Bug (Critical)
|
||||
|
||||
### Symptom
|
||||
Build หรือ dev server compile ส่ง SyntaxError แปลกๆ เช่น:
|
||||
```
|
||||
SyntaxError: Unexpected token (50:3)
|
||||
49 | return (
|
||||
> 50 | <>
|
||||
| ^
|
||||
```
|
||||
เกิดขึ้นกับ **เฉพาะไฟล์ที่มี**:
|
||||
1. Fragment shorthand `<>` (แทน `<React.Fragment>`)
|
||||
2. **Thai text หรือ non-ASCII text** ใน JSX attributes/props ของ elements ภายใน fragment
|
||||
|
||||
ถ้าไฟล์มี `<>` แต่ไม่มี Thai text → compile ผ่าน
|
||||
ถ้าไฟล์มี Thai text แต่ใช้ `<React.Fragment>` → compile ผ่าน
|
||||
|
||||
### Root Cause
|
||||
Next.js 15.3.8 มี SWC compiler bug ที่ค้าง stale cache ของ SyntaxError ไว้แม้หลังแก้ไขไฟล์แล้ว
|
||||
|
||||
### Workaround (2 วิธี)
|
||||
**วิธีที่ 1 — เปลี่ยนจาก `<>` เป็น `<React.Fragment>` หรือ `<Fragment>`:**
|
||||
```tsx
|
||||
import { Fragment } from 'react'
|
||||
// แทน:
|
||||
return <>
|
||||
<div>...</div>
|
||||
</>
|
||||
// ใช้:
|
||||
return <Fragment><div>...</div></Fragment>
|
||||
```
|
||||
|
||||
**วิธีที่ 2 — เขียน component ใหม่ทั้งหมด (แนะนำ):**
|
||||
ถ้า component มี fragment shorthand + Thai text เยอะ ให้เขียนใหม่โดยใช้ pattern ที่ไม่มีปัญหา:
|
||||
- ใส่ `return (...)` โดยไม่มี `<>` ครอบ
|
||||
- ใช้ wrapper `<div>` แทน fragment ถ้าเป็นไปได้
|
||||
- ถ้าต้องใช้ fragment ใช้ `<Fragment>`
|
||||
|
||||
### How to Detect
|
||||
```bash
|
||||
# ดูว่าไฟล์มี fragment shorthand และ Thai text หรือไม่
|
||||
grep -l "<>" src/app/\(frontend\)/**/*.tsx | xargs grep -l "[ก-๙]"
|
||||
```
|
||||
|
||||
### Prevention
|
||||
หลีกเลี่ยงการใช้ `<>` shorthand ใน component ที่มี Thai text — ใช้ `<div>` wrapper หรือ `<Fragment>` แทนเสมอ
|
||||
|
||||
---
|
||||
|
||||
## ConsentLogs: Default Export Required
|
||||
|
||||
Payload CMS บางเวอร์ชัน require ว่า collection config ที่สร้างเองต้องใช้ **default export** ไม่ใช่ named export
|
||||
|
||||
```ts
|
||||
// ✅ ถูกต้อง
|
||||
const ConsentLogs: CollectionConfig = { ... }
|
||||
export default ConsentLogs
|
||||
|
||||
// ❌ ผิด — named export จะทำให้ Payload มองไม่เห็น collection
|
||||
export const ConsentLogs = { ... }
|
||||
```
|
||||
|
||||
ถ้า collection ไม่ปรากฏใน Payload admin → ตรวจสอบว่าใช้ `export default` ไม่ใช่ `export const`
|
||||
|
||||
---
|
||||
|
||||
## Payload Access Functions: Must Be Separate File
|
||||
|
||||
Payload CMS ไม่รู้จัก `access` property ที่เป็น inline function ใน collection config — ต้องแยกออกมาเป็นไฟล์
|
||||
|
||||
**ถูกต้อง:** `src/collections/access.ts`
|
||||
```ts
|
||||
import type { Access } from 'payload'
|
||||
|
||||
export const admins: Access = () => true
|
||||
export const anyone: Access = () => true
|
||||
```
|
||||
|
||||
**แล้ว import ใน collection:**
|
||||
```ts
|
||||
import { admins } from './access'
|
||||
const MyCollection: CollectionConfig = {
|
||||
access: { create: admins },
|
||||
}
|
||||
```
|
||||
|
||||
**ผิด:** inline function ใน collection config จะถูก strip หรือไม่ทำงาน
|
||||
|
||||
---
|
||||
|
||||
## Dev Mode: IP Access + allowedDevOrigins
|
||||
|
||||
เมื่อรัน dev server แล้วเข้าผ่าน IP address (เช่น `110.164.146.185:3000`) จะมี warning:
|
||||
```
|
||||
Access to server at IP from the development server is blocked by CORS policy.
|
||||
allowedDevOrigins
|
||||
```
|
||||
|
||||
### Fix: เพิ่ม allowedDevOrigins ใน next.config.ts
|
||||
```ts
|
||||
const nextConfig: NextConfig = {
|
||||
allowedDevOrigins: ['110.164.146.185', '110.164.146.185:3000'],
|
||||
}
|
||||
```
|
||||
|
||||
### Docker: อย่าลืม Restart + Clear Cache หลังแก้ไข
|
||||
```bash
|
||||
docker exec <container> rm -rf /home/node/app/.next
|
||||
docker restart <container>
|
||||
# รอ warm up 10-40 วินาที แล้วค่อยเทสต์
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SWC Cache: Stale Cache หลังแก้ไข Error
|
||||
|
||||
ถ้าแก้ไข syntax error แล้ว dev server ยังแสดง error เดิม → SWC cache ค้าง
|
||||
|
||||
**วิธีแก้:**
|
||||
```bash
|
||||
# ลบ .next cache
|
||||
rm -rf .next
|
||||
|
||||
# ถ้าใช้ Docker
|
||||
docker exec <container> rm -rf /home/node/app/.next
|
||||
docker restart <container>
|
||||
```
|
||||
|
||||
**สาเหตุ:** Next.js 15 SWC compiler cache ระดับ binary ค้างอยู่ใน `.next/cache/swc`
|
||||
|
||||
---
|
||||
|
||||
## sitemap.xml Route (Next.js App Router)
|
||||
|
||||
`MetadataRoute.Sitemap` as a **default export function** fails with 500/timeout in Next.js App Router. The correct pattern:
|
||||
|
||||
```ts
|
||||
// ✅ ถูกต้อง — ใช้ GET handler + new Response()
|
||||
export async function GET(): Promise<Response> {
|
||||
const pages = [/* ... */]
|
||||
|
||||
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
${pages.map(p => ` <url><loc>${p.url}</loc>...</url>`).join('\n')}
|
||||
</urlset>`
|
||||
|
||||
return new Response(xml, {
|
||||
headers: { 'Content-Type': 'application/xml' },
|
||||
})
|
||||
}
|
||||
|
||||
// ❌ ผิด — MetadataRoute.Sitemap as default export
|
||||
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||
// ...returns array — causes 500 in some Next.js versions
|
||||
}
|
||||
```
|
||||
|
||||
Payload first request ช้ามาก (7-35s) ทำให้ sitemap timeout — ใช้ fallback static data:
|
||||
|
||||
```ts
|
||||
const STATIC_PAGES = [
|
||||
{ url: 'https://example.com/', priority: 1.0, changefreq: 'weekly' },
|
||||
// ...
|
||||
]
|
||||
|
||||
export async function GET(): Promise<Response> {
|
||||
let pages: string[] = []
|
||||
try {
|
||||
const payload = await getPayload({ config })
|
||||
const { docs } = await payload.find({ collection: 'pages', limit: 100 })
|
||||
pages = docs.map(d => d.slug as string)
|
||||
} catch {
|
||||
// Payload unavailable — use static fallback
|
||||
}
|
||||
|
||||
// ...build XML
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critical: `devBundleServerPackages: false` + `.next` Cache Clear = Total Failure
|
||||
|
||||
**Symptom:** หลังลบ `.next` cache แล้ว restart dev server — ทุกหน้ารวม `/` เป็น **500 error** พร้อม:
|
||||
|
||||
```
|
||||
Error: Failed to load external module payload-e448a27c99c096d3
|
||||
Cannot find package 'payload-e448a27c99c096d3'
|
||||
```
|
||||
|
||||
**Root Cause:** `withPayload(nextConfig, { devBundleServerPackages: false })` บอก Payload ว่าไม่ต้อง bundle Payload packages ลงใน `.next` แต่ Turbopack ยังอ้างถึง bundled chunk names เดิมจาก cache ที่ถูกลบไปแล้ว
|
||||
|
||||
**Fix:** ลบ `{ devBundleServerPackages: false }` ออก — ใช้แค่ `withPayload(nextConfig)`
|
||||
|
||||
```ts
|
||||
// ✅ ถูกต้อง
|
||||
export default withPayload(nextConfig)
|
||||
|
||||
// ❌ ลบออก — ทำให้ล้มเหลวหลัง clear .next cache
|
||||
export default withPayload(nextConfig, { devBundleServerPackages: false })
|
||||
```
|
||||
|
||||
**Prevention:** ถ้าต้อง clear `.next` cache เพราะ cache มีปัญหา ให้ลบ `devBundleServerPackages: false` ก่อน restart dev server
|
||||
|
||||
---
|
||||
|
||||
## robots.txt Route (Next.js App Router)
|
||||
|
||||
`MetadataRoute.Robots` as default export function causes `TypeError: NextResponse.text is not a function` error. Must use explicit GET:
|
||||
|
||||
```ts
|
||||
// ✅ ถูกต้อง
|
||||
export async function GET() {
|
||||
return new Response('User-agent: *\nAllow: /\nDisallow: /admin\n', {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
}
|
||||
|
||||
// ❌ ผิด — MetadataRoute.Robots default export
|
||||
export default function robots(): Promise<MetadataRoute.Robots> {
|
||||
return Promise.resolve({ rules: { userAgent: '*', allow: '/' } })
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## robots.txt Route (Next.js App Router)
|
||||
|
||||
**Two patterns that cause 500:**
|
||||
|
||||
1. `MetadataRoute.Robots` as default export — บาง version ทำให้ `TypeError: NextResponse.text is not a function`
|
||||
|
||||
2. **Cached file conflict** — ถ้ามี file `app/robots.txt` (ไม่ใช่ route.ts) หรือ cached file ใน `.next/dev/server/app/` อยู่ จะทำให้ route.ts handler ถูก ignore แล้ว return empty response
|
||||
|
||||
```ts
|
||||
// ✅ ถูกต้อง
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.text(
|
||||
`User-agent: *
|
||||
Allow: /
|
||||
Disallow: /admin
|
||||
Disallow: /api/
|
||||
|
||||
Sitemap: https://www.example.com/sitemap.xml
|
||||
`,
|
||||
{ headers: { 'Content-Type': 'text/plain; charset=utf-8' } }
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**ถ้า robots.txt เป็น 500 หรือว่างเปล่า:** ตรวจสอบว่าไม่มี `robots.txt` file ตรง (แทน route.ts) และลบ `.next` cache:
|
||||
|
||||
```bash
|
||||
rm -rf .next
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## sitemap.xml: Array Return = 500 Error
|
||||
|
||||
**Symptom:** `GET /sitemap.xml` returns 500 — log บอกว่าได้ `Array` แทน `Response`
|
||||
|
||||
**Root Cause:** Route handler ส่ง array ไปแทน Response object (เช่น `return [...pages, ...posts]`)
|
||||
|
||||
```ts
|
||||
// ❌ ผิด — array ไม่ใช่ Response
|
||||
export async function GET() {
|
||||
const pages = await getPages()
|
||||
return pages // ← 500 error
|
||||
}
|
||||
|
||||
// ✅ ถูกต้อง
|
||||
export async function GET() {
|
||||
const pages = await getPages()
|
||||
const xml = buildSitemapXml(pages)
|
||||
return new Response(xml, {
|
||||
headers: { 'Content-Type': 'application/xml; charset=utf-8' },
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `/sitemap` Page Conflicts with `/sitemap.xml` Route
|
||||
|
||||
ถ้ามีทั้ง `app/sitemap/page.tsx` และ `app/sitemap.xml/route.ts` — Next.js จะ route ไปที่ page.tsx ก่อน ทำให้ `/sitemap.xml` เป็น **404**
|
||||
|
||||
**Fix:** ลบ `app/sitemap/` directory ถ้ามี sitemap.xml route:
|
||||
|
||||
```bash
|
||||
rm -rf app/sitemap/
|
||||
```
|
||||
|
||||
ตรวจสอบ: `ls app/` อย่างน้อยต้องมีไฟล์ `.xml` ไม่ใช่ directory ที่ชื่อเดียวกัน
|
||||
|
||||
---
|
||||
|
||||
## Bulk Insert Posts ใน MongoDB (Direct via mongosh)
|
||||
|
||||
เมื่อ Payload REST API (`POST /api/posts`) ตอบ `500: Something went wrong` เวลา insert richText/Lexical field โดยตรง สามารถใช้ **direct MongoDB insert** แทนได้
|
||||
|
||||
### วิธีทำ
|
||||
```bash
|
||||
# เขียน script เป็นไฟล์ .cjs (CommonJS)
|
||||
# รันโดยตรงจาก host (ไม่ต้องเข้า container)
|
||||
node seed-mongo.cjs
|
||||
```
|
||||
|
||||
### หา MongoDB URL
|
||||
```bash
|
||||
grep MONGODB_URL .env
|
||||
# ถ้าใช้ Docker: mongodb://localhost:27017/portal-mini-store
|
||||
# ถ้าใช้ Atlas: mongodb+srv://user:pass@cluster.mongodb.net/dbname
|
||||
```
|
||||
|
||||
### Payload SDK Seed Fails ด้วย spawn Error
|
||||
ถ้า seed script ที่ใช้ Payload SDK (`getPayload()`) ขึ้น error เช่น `spawn is not defined` หรือ `node not found` — นั่นคือ Payload SDK ภายในมีการ `spawn('node')` ซึ่งล้มเหลวในบาง environment
|
||||
|
||||
**วิธีแก้: ใช้ MongoDB driver โดยตรง (CommonJS)**
|
||||
```js
|
||||
// seed-mongo.cjs — CommonJS เท่านั้น (require, not import)
|
||||
const { MongoClient } = require('mongodb')
|
||||
|
||||
async function main() {
|
||||
const client = new MongoClient(process.env.MONGODB_URL)
|
||||
await client.connect()
|
||||
const db = client.db()
|
||||
|
||||
// insert posts
|
||||
const posts = [/* ... */]
|
||||
for (const post of posts) {
|
||||
const result = await db.collection('posts').insertOne({
|
||||
...post,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
console.log('Inserted:', post.title, result.insertedId)
|
||||
}
|
||||
|
||||
await client.close()
|
||||
}
|
||||
|
||||
main().catch(console.error)
|
||||
```
|
||||
|
||||
### Lexical Content Format ขั้นต่ำ
|
||||
```js
|
||||
content: {
|
||||
root: {
|
||||
type: 'root',
|
||||
children: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [{ type: 'text', text: 'your excerpt or content here' }]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### หา Mongo Container Name
|
||||
```bash
|
||||
docker ps --format '{{.Names}}' # ดู container names
|
||||
# ถ้าใช้ docker-compose จะเป็น <project>-mongo หรือ <project>-db
|
||||
```
|
||||
|
||||
### ตรวจสอบว่า Posts ถูก Insert แล้วผ่าน Payload API
|
||||
```bash
|
||||
docker exec <app-container> node -e "
|
||||
fetch('http://localhost:3000/api/posts?limit=15')
|
||||
.then(r => r.json())
|
||||
.then(d => { console.log('Total:', d.totalDocs); d.docs.forEach(p => console.log(' -', p.title)); })
|
||||
"
|
||||
```
|
||||
|
||||
### ข้อควรระวัง
|
||||
- Insert ตรงๆ ผ่าน MongoDB จะ bypass Payload access control
|
||||
- ถ้ามี auth token ต้องใช้ Payload API แทน
|
||||
- richText field ต้องเป็น Lexical JSON format (ดูด้านบน)
|
||||
177
skills/website-creator/references/questions.md
Normal file
177
skills/website-creator/references/questions.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Pre-Project Questions
|
||||
|
||||
## คำถามก่อนเริ่มโปรเจค
|
||||
|
||||
ใช้เป็นแนวทางถามคำถามลูกค้าก่อนเริ่มสร้างเว็บไซต์
|
||||
|
||||
---
|
||||
|
||||
## 1. ข้อมูลพื้นฐาน
|
||||
|
||||
1.1 **ชื่อเว็บไซต์/บริษัท**
|
||||
- ชื่อที่จะแสดงบนเว็บ
|
||||
- ชื่อในเอกสาร (ถ้าต่างจากชื่อบนเว็บ)
|
||||
|
||||
1.2 **ทำอะไร?**
|
||||
- ขายสินค้าอะไร?
|
||||
- ให้บริการอะไร?
|
||||
- มี unique selling point อะไร?
|
||||
|
||||
---
|
||||
|
||||
## 2. กลุ่มเป้าหมาย
|
||||
|
||||
2.1 **กลุ่มลูกค้าเป้าหมาย**
|
||||
- อายุ, เพศ, อาชีพ
|
||||
- พฤติกรรมการใช้ internet
|
||||
- ปัญหาที่ต้องการแก้ไข
|
||||
|
||||
2.2 **ต้องการเข้าถึงตลาดไหน?**
|
||||
- ภายในประเทศ (ไทย)
|
||||
- ต่างประเทศ
|
||||
- ทั้งในและต่างประเทศ
|
||||
|
||||
---
|
||||
|
||||
## 3. เว็บไซต์เดิม
|
||||
|
||||
3.1 **มีเว็บอยู่แล้วหรือยัง?**
|
||||
- ถ้ามี: URL ของเว็บเก่า
|
||||
- ถ้ามี: ทำไมอยากเปลี่ยน?
|
||||
- ถ้ามี: มี source code ไหม?
|
||||
|
||||
3.2 **มี domain และ hosting แล้วหรือยัง?**
|
||||
- ถ้ามี: provider อะไร?
|
||||
- ถ้ามี: domain ชื่ออะไร?
|
||||
|
||||
---
|
||||
|
||||
## 4. ดีไซน์และ Branding
|
||||
|
||||
4.1 **มี brand guidelines ไหม?**
|
||||
- Logo files
|
||||
- สีที่ใช้ (color palette)
|
||||
- Typography
|
||||
- ภาพประกอบที่มี
|
||||
|
||||
4.2 **ชอบดีไซน์แบบไหน?**
|
||||
- Minimal / Clean
|
||||
- Bold / Eye-catching
|
||||
- Creative / Artistic
|
||||
- Corporate / Professional
|
||||
- Modern / Futuristic
|
||||
|
||||
4.3 **ชอบ Dark Mode, Light Mode หรือทั้งสอง?**
|
||||
- Light mode อย่างเดียว
|
||||
- Dark mode อย่างเดียว
|
||||
- ทั้งสอง (user เลือกได้)
|
||||
|
||||
4.4 **มีเว็บที่ชอบเป็น reference ไหม?**
|
||||
- URL(s) ของเว็บที่ชอบ
|
||||
- ชอบอะไรจากเว็บนั้น?
|
||||
|
||||
---
|
||||
|
||||
## 5. หน้าที่ต้องการ
|
||||
|
||||
5.1 **ต้องการหน้าอะไรบ้าง?**
|
||||
- [ ] Home
|
||||
- [ ] About Us / บริษัทของเรา
|
||||
- [ ] Services / บริการ
|
||||
- [ ] Products / สินค้า
|
||||
- [ ] Portfolio / ผลงาน
|
||||
- [ ] Blog / ข่าวสาร
|
||||
- [ ] Contact / ติดต่อ
|
||||
- [ ] FAQ / คำถามที่พบบ่อย
|
||||
- [ ] Careers / ร่วมงานกับเรา
|
||||
- [ ] Other: ____________
|
||||
|
||||
5.2 **มีฟอร์มที่ต้องการไหม?**
|
||||
- [ ] Contact Form
|
||||
- [ ] Quote Request Form
|
||||
- [ ] Newsletter Signup
|
||||
- [ ] Booking Form
|
||||
- [ ] Registration Form
|
||||
- [ ] Other: ____________
|
||||
|
||||
---
|
||||
|
||||
## 6. ฟังก์ชันพิเศษ
|
||||
|
||||
6.1 **ต้องการระบบจัดการเนื้อหา (CMS) ไหม?**
|
||||
- ใช้เพื่ออะไร?
|
||||
- ใครจะเป็นคนใช้?
|
||||
- ต้องการให้แอดมินทำอะไรได้บ้าง?
|
||||
|
||||
6.2 **ต้องการระบบ E-commerce ไหม?**
|
||||
- มีสินค้ากี่ชิ้น?
|
||||
- ต้องการ payment gateway อะไร?
|
||||
- ต้องการ shipping integration ไหม?
|
||||
|
||||
6.3 **ต้องการระบบสมาชิก/ล็อกอินไหม?**
|
||||
- สมาชิกทำอะไรได้บ้าง?
|
||||
- มีกี่ role? (admin, member, etc.)
|
||||
|
||||
---
|
||||
|
||||
## 7. Technical Requirements
|
||||
|
||||
7.1 **มี SMTP/Email server ไหม?**
|
||||
- สำหรับส่ง email จากเว็บ
|
||||
- เช่น contact form, newsletter
|
||||
|
||||
7.2 **มี Google Analytics หรือ Marketing tools ไหม?**
|
||||
- GA4 Tracking ID
|
||||
- Facebook Pixel
|
||||
- Other tracking codes
|
||||
|
||||
7.3 **มี Third-party integrations ไหม?**
|
||||
- Payment gateways
|
||||
- CRM systems
|
||||
- Other APIs
|
||||
|
||||
---
|
||||
|
||||
## 8. PDPA Compliance
|
||||
|
||||
8.1 **มี DPO (Data Protection Officer) หรือยัง?**
|
||||
- ถ้ายัง: ต้องการให้ช่วยจัดหาไหม?
|
||||
|
||||
8.2 **เว็บจะเก็บข้อมูลอะไรบ้าง?**
|
||||
- ข้อมูลลูกค้า
|
||||
- ข้อมูลการสั่งซื้อ
|
||||
- Newsletter subscribers
|
||||
- Other: ____________
|
||||
|
||||
8.3 **ต้องการ Cookie Consent Popup ไหม?**
|
||||
- ใช้ cookies อะไรบ้าง?
|
||||
- ต้องการให้ users มีทางเลือกไหม?
|
||||
|
||||
---
|
||||
|
||||
## 9. งบประมาณและ Timeline
|
||||
|
||||
9.1 **งบประมาณ**
|
||||
- ต้องการทำเท่าไหร่?
|
||||
- มีงบแบบไหน? (fixed/negotiable)
|
||||
|
||||
9.2 **ต้องการให้เสร็จเมื่อไหร่?**
|
||||
- มี deadline ไหม?
|
||||
- มีเหตุการณ์พิเศษที่ต้องเสร็จก่อนไหม?
|
||||
|
||||
---
|
||||
|
||||
## Checklist สำหรับ Website Creator
|
||||
|
||||
เมื่อถามครบแล้ว ให้ตรวจสอบ:
|
||||
|
||||
- [ ] ชื่อเว็บ/บริษัท
|
||||
- [ ] ธุรกิจทำอะไร
|
||||
- [ ] กลุ่มเป้าหมาย
|
||||
- [ ] เว็บเก่า (ถ้ามี)
|
||||
- [ ] Style ที่ต้องการ
|
||||
- [ ] หน้าที่ต้องการ
|
||||
- [ ] CMS ต้องการไหม
|
||||
- [ ] Email/SMTP
|
||||
- [ ] PDPA/DPO
|
||||
- [ ] งบและ timeline
|
||||
312
skills/website-creator/references/sitemap-template.md
Normal file
312
skills/website-creator/references/sitemap-template.md
Normal file
@@ -0,0 +1,312 @@
|
||||
# Sitemap Template
|
||||
|
||||
สร้าง sitemap ตามคำตอบจาก pre-project questions
|
||||
|
||||
---
|
||||
|
||||
## Basic Sitemap Structure
|
||||
|
||||
```
|
||||
/
|
||||
├── index # Home (หน้าแรก)
|
||||
├── about # About Us (เกี่ยวกับเรา)
|
||||
├── services/ # Services Index (รายการบริการ)
|
||||
│ ├── index # Services list
|
||||
│ └── [slug] # Service detail page
|
||||
├── blog/ # Blog Index (รายการบทความ)
|
||||
│ ├── index # Blog list
|
||||
│ └── [slug] # Blog post page
|
||||
├── contact # Contact (ติดต่อ)
|
||||
├── privacy-policy # Privacy Policy (นโยบายความเป็นส่วนตัว)
|
||||
├── terms-of-service # Terms of Service (เงื่อนไขการให้บริการ)
|
||||
├── login # Login (เข้าสู่ระบบ)
|
||||
├── register # Register (สมัครสมาชิก)
|
||||
├── account/ # Account Dashboard (หน้าบัญชีผู้ใช้)
|
||||
│ ├── index # Dashboard overview
|
||||
│ ├── profile # Edit profile
|
||||
│ ├── orders # Order history
|
||||
│ └── settings # Account settings
|
||||
├── (optional modules...)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Optional Modules
|
||||
|
||||
### Blog Module
|
||||
```
|
||||
/blog/
|
||||
├── index # All posts
|
||||
├── [slug] # Single post
|
||||
└── category/[category]/ # Filter by category
|
||||
└── index
|
||||
```
|
||||
|
||||
### Portfolio Module
|
||||
```
|
||||
/portfolio/
|
||||
├── index # Gallery overview
|
||||
└── [slug] # Single portfolio item
|
||||
```
|
||||
|
||||
### Product Catalog Module
|
||||
```
|
||||
/products/
|
||||
├── index # Product listing
|
||||
├── [slug] # Product detail
|
||||
└── category/[category]/ # Filter by category
|
||||
└── index
|
||||
```
|
||||
|
||||
### FAQ Module
|
||||
```
|
||||
/faq/
|
||||
└── index # FAQ page (accordion style)
|
||||
```
|
||||
|
||||
### Team Module
|
||||
```
|
||||
/team/
|
||||
├── index # Team list
|
||||
└── [slug] # Team member profile
|
||||
```
|
||||
|
||||
### Pricing Module
|
||||
```
|
||||
/pricing/
|
||||
└── index # Pricing plans page
|
||||
```
|
||||
|
||||
### Careers Module
|
||||
```
|
||||
/careers/
|
||||
├── index # Job listings
|
||||
└── [slug] # Job detail
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SEO Sitemap Structure
|
||||
|
||||
### XML Sitemap (sitemap.xml)
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>{SITE_URL}/</loc>
|
||||
<lastmod>{DATE}</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>{SITE_URL}/about/</loc>
|
||||
<lastmod>{DATE}</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<!-- เพิ่มทุกหน้าที่ต้องการ index -->
|
||||
</urlset>
|
||||
```
|
||||
|
||||
### robots.txt
|
||||
```
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: {SITE_URL}/sitemap.xml
|
||||
|
||||
# Block admin areas
|
||||
Disallow: /admin/
|
||||
Disallow: /api/
|
||||
Disallow: /account/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Page Meta Template
|
||||
|
||||
สร้าง meta information สำหรับแต่ละหน้า:
|
||||
|
||||
| Page | Title (TH) | Title (EN) | Description (TH) | Keywords |
|
||||
|------|-----------|-----------|-----------------|----------|
|
||||
| Home | {SITE_NAME} - {TAGLINE} | {SITE_NAME} | {DESCRIPTION} | {KEYWORDS} |
|
||||
| About | เกี่ยวกับ {SITE_NAME} | About Us | {DESCRIPTION} | {KEYWORDS} |
|
||||
| Services | บริการของ {SITE_NAME} | Our Services | {DESCRIPTION} | {KEYWORDS} |
|
||||
| Blog | บทความ | Blog | {DESCRIPTION} | {KEYWORDS} |
|
||||
| Contact | ติดต่อ {SITE_NAME} | Contact Us | {DESCRIPTION} | {KEYWORDS} |
|
||||
| Privacy Policy | นโยบายความเป็นส่วนตัว | Privacy Policy | {DESCRIPTION} | privacy, pdpa, {KEYWORDS} |
|
||||
| Terms | เงื่อนไขการให้บริการ | Terms of Service | {DESCRIPTION} | terms, {KEYWORDS} |
|
||||
|
||||
---
|
||||
|
||||
## Content Structure Example
|
||||
|
||||
```
|
||||
src/
|
||||
├── content/
|
||||
│ ├── pages/
|
||||
│ │ ├── home.md
|
||||
│ │ ├── about.md
|
||||
│ │ ├── contact.md
|
||||
│ │ ├── privacy-policy.md
|
||||
│ │ └── terms-of-service.md
|
||||
│ ├── blog/
|
||||
│ │ ├── post-1.md
|
||||
│ │ ├── post-2.md
|
||||
│ │ └── ...
|
||||
│ ├── services/
|
||||
│ │ ├── service-1.md
|
||||
│ │ └── ...
|
||||
│ └── team/
|
||||
│ ├── member-1.md
|
||||
│ └── ...
|
||||
├── layouts/
|
||||
│ ├── BaseLayout.astro
|
||||
│ ├── PageLayout.astro
|
||||
│ ├── BlogLayout.astro
|
||||
│ └── AuthLayout.astro
|
||||
├── components/
|
||||
│ ├── Navigation.astro
|
||||
│ ├── Footer.astro
|
||||
│ ├── Hero.astro
|
||||
│ ├── ServiceCard.astro
|
||||
│ ├── BlogCard.astro
|
||||
│ ├── ContactForm.astro
|
||||
│ ├── CookieConsent.astro
|
||||
│ └── ...
|
||||
└── pages/
|
||||
├── index.astro
|
||||
├── about.astro
|
||||
├── services/
|
||||
│ ├── index.astro
|
||||
│ └── [slug].astro
|
||||
├── blog/
|
||||
│ ├── index.astro
|
||||
│ └── [slug].astro
|
||||
├── contact.astro
|
||||
├── privacy-policy.astro
|
||||
├── terms-of-service.astro
|
||||
├── login.astro
|
||||
├── register.astro
|
||||
└── account/
|
||||
├── index.astro
|
||||
├── profile.astro
|
||||
├── orders.astro
|
||||
└── settings.astro
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Navigation Structure
|
||||
|
||||
### Desktop Navigation
|
||||
```
|
||||
[Logo] Home | Services | Blog | About | Contact [Login] [Register]
|
||||
```
|
||||
|
||||
### Mobile Navigation (Hamburger)
|
||||
```
|
||||
☰ [Logo]
|
||||
─────────
|
||||
Home
|
||||
Services
|
||||
Blog
|
||||
About
|
||||
Contact
|
||||
─────────
|
||||
Login
|
||||
Register
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Footer Structure
|
||||
```
|
||||
[Logo + Tagline]
|
||||
|
||||
[Links Column 1] [Links Column 2] [Links Column 3] [Contact]
|
||||
- หน้าแรก - บริการ - บทความ - {ADDRESS}
|
||||
- เกี่ยวกับเรา - ผลงาน - คำถามที่พบบ่อย - {PHONE}
|
||||
- ติดต่อเรา - ติดต่อ - นโยบายความเป็นส่วนตัว - {EMAIL}
|
||||
- สมัครสมาชิก - เงื่อนไขการให้บริการ
|
||||
|
||||
Copyright (c) {YEAR} {SITE_NAME} | Built with Astro
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## JSON-LD Structured Data
|
||||
|
||||
### Organization Schema
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"name": "{SITE_NAME}",
|
||||
"url": "{SITE_URL}",
|
||||
"logo": "{SITE_URL}/logo.png",
|
||||
"description": "{DESCRIPTION}",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"streetAddress": "{ADDRESS}",
|
||||
"addressLocality": "{CITY}",
|
||||
"addressCountry": "TH"
|
||||
},
|
||||
"contactPoint": {
|
||||
"@type": "ContactPoint",
|
||||
"telephone": "{PHONE}",
|
||||
"contactType": "customer service"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### LocalBusiness Schema (ถ้ามีร้านค้า)
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "LocalBusiness",
|
||||
"name": "{SITE_NAME}",
|
||||
"image": "{SITE_URL}/og-image.jpg",
|
||||
"priceRange": "{PRICE_RANGE}",
|
||||
"address": {...},
|
||||
"openingHoursSpecification": {...},
|
||||
"aggregateRating": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### WebSite Schema
|
||||
```json
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
"name": "{SITE_NAME}",
|
||||
"url": "{SITE_URL}",
|
||||
"potentialAction": {
|
||||
"@type": "SearchAction",
|
||||
"target": "{SITE_URL}/search?q={search_term_string}",
|
||||
"query-input": "required name=search_term_string"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- ทุกหน้าต้องมี:
|
||||
- Title tag (unique)
|
||||
- Meta description (unique)
|
||||
- Open Graph tags
|
||||
- Canonical URL
|
||||
- Structured data (ถ้าเหมาะสม)
|
||||
|
||||
- หน้า Privacy Policy และ Terms of Service ต้องมี:
|
||||
- วันที่มีผลบังคับใช้
|
||||
- วันที่แก้ไขล่าสุด
|
||||
- ข้อมูล DPO
|
||||
- ลิงก์ถึงกัน
|
||||
|
||||
- หน้า Contact ต้องมี:
|
||||
- แบบฟอร์มติดต่อ (ทำงานจริง)
|
||||
- ข้อมูลติดต่อ (ที่อยู่, โทร, อีเมล)
|
||||
- แผนที่ (ถ้ามีร้านค้า)
|
||||
Reference in New Issue
Block a user