From c8cf03a7259d4395dcf496b98419bc3de10dd8e6 Mon Sep 17 00:00:00 2001 From: Kunthawat Greethong Date: Mon, 1 Jun 2026 15:44:02 +0700 Subject: [PATCH] Add EmDash CMS blog + hero standardization + seed fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add EmDash CMS integration with SQLite and local storage - Add blog collection (seed/seed.json) with 3 sample posts - Add /บทความ list page and /บทความ/[slug] detail page - Add blog section to homepage - Fix reserved field slugs (slug, published_at removed from fields) - Fix date field mapping (publishedAt camelCase) - Fix featured image URL for admin-uploaded images (meta.storageKey) - Standardize all product page hero sections - Update navigation with 'บทความ' link - Configure Google OAuth provider --- .gitignore | 17 + EMDASH-SETUP-GUIDE.md | 217 + astro.config.mjs | 22 +- package-lock.json | 5067 +++++++++++++++++++++++- package.json | 8 +- seed/seed.json | 137 + src/layouts/BaseLayout.astro | 6 + src/live.config.ts | 6 + src/pages/aeroflex.astro | 4 +- src/pages/armflex.astro | 4 +- src/pages/durgo-avvs.astro | 6 +- src/pages/grilles.astro | 6 +- src/pages/index.astro | 82 + src/pages/maxflex.astro | 4 +- src/pages/pipe-coupling.astro | 6 +- src/pages/realflex.astro | 19 +- src/pages/water-pump.astro | 6 +- src/pages/water-treatment.astro | 19 +- src/pages/ตู้ดับเพลิง.astro | 6 +- src/pages/ท่อ-hdpe.astro | 2 - src/pages/ท่อ-ppr-scg.astro | 2 - src/pages/ท่อ-ppr-thai-ppr.astro | 2 - src/pages/ท่อ-syler.astro | 6 +- src/pages/ท่อ-upvc.astro | 2 - src/pages/ท่อ-xy-lent.astro | 15 +- src/pages/บทความ/[slug].astro | 130 + src/pages/บทความ/index.astro | 86 + src/pages/ระบบน้ำ.astro | 2 - src/pages/ระบบรั้วไวน์แมน.astro | 19 +- src/pages/รั้วเทวดา.astro | 15 +- src/pages/วาล์ว-valve.astro | 11 +- src/pages/เครื่องเชื่อม-hdpe.astro | 6 +- src/pages/เครื่องเชื่อม-ppr.astro | 6 +- src/pages/เทอร์โมเบรค-thermobreak.astro | 19 +- src/pages/เม็กกรู๊ฟ-คับปลิ้ง.astro | 6 +- 35 files changed, 5786 insertions(+), 185 deletions(-) create mode 100644 EMDASH-SETUP-GUIDE.md create mode 100644 seed/seed.json create mode 100644 src/live.config.ts create mode 100644 src/pages/บทความ/[slug].astro create mode 100644 src/pages/บทความ/index.astro diff --git a/.gitignore b/.gitignore index ed362a0..396823a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,20 @@ dist/ .DS_Store *.swp *.swo + +# Database +*.db +*.db-shm +*.db-wal +*.bak +*.old +*.test-run + +# Agent context +.context/ + +# Uploaded media +uploads/ + +# Generated +emdash-env.d.ts diff --git a/EMDASH-SETUP-GUIDE.md b/EMDASH-SETUP-GUIDE.md new file mode 100644 index 0000000..b2baab1 --- /dev/null +++ b/EMDASH-SETUP-GUIDE.md @@ -0,0 +1,217 @@ +# EmDash CMS Integration Guide + +## Overview +This document summarizes the problems encountered and solutions when integrating EmDash CMS into an existing Astro static site, covering seed file setup, template design, and image/media handling. + +--- + +## 1. Database & Seed File + +### 1.1 Reserved Field Slugs + +**Problem**: Adding `slug` or `published_at` as collection fields in `seed.json` causes the seed to fail. The `ec_blog` table is created but custom fields (like `excerpt`, `body`, `featured_image`) never get their columns added, resulting in errors like: +``` +SqliteError: table ec_blog has no column named excerpt +``` + +**Root Cause**: EmDash has a `RESERVED_FIELD_SLUGS` set in `node_modules/emdash/src/schema/types.ts` that includes: +- `id`, `slug`, `status`, `author_id`, `primary_byline_id` +- `created_at`, `updated_at`, `published_at`, `scheduled_at`, `deleted_at` +- `version`, `live_revision_id`, `draft_revision_id`, `locale`, `translation_group` +- Plus runtime-hydrated fields: `terms`, `bylines`, `byline` + +When `createField()` encounters a reserved slug, it **throws a SchemaError**, which stops the transaction and prevents all subsequent fields from being created. + +**Fix**: Do NOT include reserved slugs in the `fields` array of your collection definition. The system already creates these columns automatically in the content table (e.g., `ec_blog`). + +```json +// ❌ WRONG - slug and published_at are reserved +"fields": [ + { "slug": "title", "type": "string" }, + { "slug": "slug", "type": "slug" }, + { "slug": "excerpt", "type": "text" }, + { "slug": "published_at", "type": "datetime" } +] + +// ✅ CORRECT - only define custom fields +"fields": [ + { "slug": "title", "type": "string" }, + { "slug": "excerpt", "type": "text" }, + { "slug": "body", "type": "portableText" }, + { "slug": "featured_image", "type": "image" }, + { "slug": "tags", "type": "string" } +] +``` + +### 1.2 Database Reset + +**Problem**: The old database (`data.db`) caches schema and seed data. Changes to `seed.json` aren't reflected unless the database is fully deleted. + +**Fix**: Remove all database files before restarting: +```bash +cd /path/to/project +rm -f data.db data.db-shm data.db-wal +npm run dev +``` + +The `npx emdash dev` command hardcodes port 4321 and ignores `astro.config.mjs`'s `server.port` setting. Always use `npm run dev` for daily development. + +### 1.3 Seed Content Data Format + +**Problem**: Content entries in the seed file must only include non-system fields in `data`. System fields like `slug`, `status`, `published_at` are stored as direct columns on the `ec_*` table - they go at the same level as `data`, not inside it. + +```json +// ✅ CORRECT structure +{ + "id": "my-post", + "slug": "my-slug", + "status": "published", + "data": { + "title": "My Title", + "excerpt": "Description", + "featured_image": { + "src": "/images/photo.jpg", + "alt": "Photo description" + }, + "body": [ + { + "_type": "block", + "style": "normal", + "children": [ + { "_type": "span", "text": "Hello world" } + ] + } + ], + "tags": "news" + } +} +``` + +--- + +## 2. Template Data Access + +### 2.1 Date Field Name (published_at -> publishedAt) + +**Problem**: In templates, `article.data.published_at` returns `undefined`, showing "Invalid Date". + +**Root Cause**: EmDash's loader (`mapRowToData` in `node_modules/emdash/src/loader.ts`) maps system date columns to **camelCase** using an `INCLUDE_IN_DATA` map: +```js +const INCLUDE_IN_DATA = { + published_at: "publishedAt", + created_at: "createdAt", + updated_at: "updatedAt", + scheduled_at: "scheduledAt", +}; +``` + +**Fix**: Use camelCase property names in templates: +```astro +{/* ❌ WRONG */} +