feat(thai-frontend-dev): update consent system to better-sqlite3

- Replace Astro DB with better-sqlite3 (bypasses remote SQLite limitation)
- Add consent API with auto-create table pattern
- Update admin dashboard to fetch from API instead of Astro DB
- Add IP hashing and rate limiting for GDPR compliance
- Add seo-utils-mcp-guide skill
- Update legal templates with business placeholders
This commit is contained in:
Kunthawat Greethong
2026-04-01 18:36:51 +07:00
parent e4d41e3ae5
commit 5053ccdba2
6 changed files with 539 additions and 499 deletions

View File

@@ -22,7 +22,7 @@ Create and deploy **PDPA-compliant** Astro websites on Easypanel automatically w
-**Bilingual support** (Thai/English)
-**Umami Analytics** (privacy-first, no cookies)
-**Cookie consent management** (astro-consent)
-**Consent logging database** (Astro DB + Turso)
-**Consent logging database** (better-sqlite3 - direct SQLite, bypasses Astro DB limitation)
-**PDPA-compliant legal pages** (Privacy Policy, Terms)
-**Easypanel deployment** (Docker, auto-deploy)
@@ -256,22 +256,26 @@ Create and deploy **PDPA-compliant** Astro websites on Easypanel automatically w
- One-click withdrawal
- Immediate script unloading
**Database Schema (ConsentLog):**
**Database Schema (ConsentLog - better-sqlite3):**
```typescript
{
id: number (PK),
sessionId: string (unique),
timestamp: datetime,
locale: 'en' | 'th',
essential: boolean,
analytics: boolean,
marketing: boolean,
id: number (PK, autoincrement),
sessionId: string (UNIQUE),
timestamp: datetime (ISO string),
essential: boolean (0/1),
analytics: boolean (0/1),
marketing: boolean (0/1),
policyVersion: string,
ipHash: string (SHA256, first 16 chars),
userAgent: string
}
```
**Why better-sqlite3 instead of Astro DB?**
- Astro DB cannot create new tables with remote SQLite (`ASTRO_DB_REMOTE_URL=file:...`)
- better-sqlite3 bypasses this limitation completely
- Auto-creates table on API startup (`CREATE TABLE IF NOT EXISTS`)
---
### Phase 5: Umami Analytics Integration
@@ -336,34 +340,36 @@ Create and deploy **PDPA-compliant** Astro websites on Easypanel automatically w
### Phase 7: Docker Setup
**Dockerfile:**
**Dockerfile (better-sqlite3):**
```dockerfile
FROM node:20-alpine AS builder
FROM node:20-alpine
WORKDIR /app
# Install build dependencies for better-sqlite3 native module
RUN apk add --no-cache python3 make g++
# Install dependencies
COPY package*.json ./
RUN npm ci
RUN npm install
# Copy source
COPY . .
# Build
RUN npm run build
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/db ./db
# SQLite runtime
RUN apk add --no-cache sqlite-libs
# Serve
EXPOSE 80
ENV NODE_ENV=production
ENV ASTRO_DB_REMOTE_URL=file:/app/data/consent.db
CMD ["sh", "-c", "mkdir -p /app/data && npx astro preview --host 0.0.0.0 --port 80"]
CMD ["npm", "run", "preview"]
```
**Key differences from Astro DB approach:**
- Uses `node:20-alpine` with build tools for native module compilation
- `better-sqlite3` creates SQLite file at `data/consent.db` automatically
- No `ASTRO_DB_REMOTE_URL` needed - bypasses Astro DB limitation
**Test Locally:**
```bash
@@ -513,9 +519,8 @@ website-name/
│ │
│ ├── pages/api/
│ │ └── consent/
│ │ ├── POST.ts
│ │ ── GET.ts
│ │ └── [sessionId]/DELETE.ts
│ │ ├── index.ts # GET, POST
│ │ ── [sessionId].ts # DELETE
│ │
│ ├── styles/
│ │ └── global.css
@@ -529,13 +534,12 @@ website-name/
│ ├── lib/
│ │ ├── i18n.ts
│ │ ├── consent.ts
│ │ └── utils.ts
│ │ └── db.ts # better-sqlite3 setup
│ │
│ └── middleware.ts
├── db/
── config.ts
│ └── seed.ts
├── data/ # SQLite database (auto-created)
── consent.db
├── Dockerfile
├── docker-compose.yml
@@ -558,11 +562,10 @@ website-name/
- **Astro 5.x** - Static site generator with i18n, hybrid rendering
- **Tailwind CSS 4.x** - Utility-first CSS framework
- **Astro DB** - SQLite database for consent logging
- **Turso** - Managed libSQL for production (optional)
- **better-sqlite3** - Direct SQLite for consent logging (bypasses Astro DB limitation)
- **astro-consent** - Cookie consent management
- **Umami Analytics** - Privacy-first web analytics
- **Docker** - Containerization
- **Docker** - Containerization (alpine for native module support)
- **Gitea** - Git repository (git.moreminimore.com)
- **Easypanel** - Deployment platform
@@ -580,15 +583,13 @@ UMAMI_DOMAIN=analytics.example.com
# Admin
ADMIN_PASSWORD=change-this-secure-password
# Database (optional - defaults to SQLite file)
ASTRO_DB_REMOTE_URL=libsql://your-db.turso.io
ASTRO_DB_APP_TOKEN=your-turso-token
# Site Configuration
SITE_URL=https://example.com
SITE_NAME="Example Website"
```
**Note:** Database (SQLite) is created automatically at `data/consent.db`. No external database needed.
**Security:**
- NEVER commit `.env` file
- Use `.env.example` as template
@@ -647,7 +648,7 @@ html {
## ⚠️ Important Notes
1. **Hybrid Rendering** - Static pages + server endpoints for API
2. **Database** - SQLite file (dev) → Turso (production, optional)
2. **Database** - better-sqlite3 (direct SQLite, auto-creates tables)
3. **Main Branch Only** - Direct to production
4. **Auto-Deploy** - Easypanel watches Git
5. **Markdown Content** - Blog/posts as Markdown files
@@ -656,6 +657,7 @@ html {
8. **Consent Logging** - Audit trail for 10+ years (PDPA requirement)
9. **Right to be Forgotten** - API endpoint for consent deletion
10. **Bilingual Default** - Thai + English with fallback
11. **Docker Alpine** - Uses alpine for better-sqlite3 native module compilation
---
@@ -757,23 +759,11 @@ npm run build
# Preview build
npm run preview
# Push DB schema (development)
npm run db:push
# Seed development data
npm run db:seed
```
### Production
```bash
# Build with remote database
npm run build --remote
# Push DB schema to Turso
npm run db:push --remote
# Docker build
docker build -t website:latest .
@@ -781,7 +771,6 @@ docker build -t website:latest .
docker run -p 80:80 \
-e UMAMI_WEBSITE_ID=xxx \
-e ADMIN_PASSWORD=secure-pass \
-e ASTRO_DB_REMOTE_URL=file:/app/data/consent.db \
website:latest
```