minhvo.vercel.app

Mon May 25 2026

Hoa Tươi Đà Nẵng — hoatuoidanangnhanhi.com

Hoa Tươi Đà Nẵng — hoatuoidanangnhanhi.com

Astro

React 19

TypeScript

Cloudflare Pages

D1

R2

Workers AI

Vectorize

RAG

TailwindCSS

E-commerce

Vietnamese flower-shop storefront on Astro 6 + React 19 islands, deployed to Cloudflare Pages with D1, R2, Workers AI + Vectorize RAG, and Cloudflare Email Routing.

Overview

A Vietnamese flower-shop e-commerce storefront for Hoa Tươi Đà Nẵng, built on Astro 6 with React 19 islands and shipped end-to-end on the Cloudflare edge — D1 for the catalog, R2 for images, KV for chat caching, Workers AI + Vectorize for the RAG chatbot, and Cloudflare Email Routing for transactional mail.

Tech Stack

LayerTechnology
FrameworkAstro 6 (static + per-page SSR via prerender = false), React 19 islands, TypeScript 5.9
StylingTailwind CSS v4 (Vite plugin), Lucide icons
EditorTipTap 3 (rich-text + tables + image extension)
Carousel / ChartsEmbla / Recharts
RuntimeCloudflare Pages with a _worker.js/ wrapper bundling Pages Functions + Astro SSR
StorageCloudflare D1 (flower-catalog), R2 (flower-images), KV (CHAT_CACHE)
AICloudflare Workers AI + Vectorize (RAG), Vercel AI SDK, Google Gemini (primary) + OpenRouter (fallback) via Cloudflare AI Gateway
EmailCloudflare Email Routing send_email binding (Resend retained as fallback)
AuthPBKDF2 password hashing, sliding 1-day session cookies, optional X-Admin-Key for CI
AnalyticsGA4 (gtag.js), GTM, Facebook Pixel — loaded through Partytown
PaymentVietQR generator (src/lib/vietqr.ts) for bank-transfer instructions
SearchD1 with diacritic-stripped search_name column + JS-side diacritic fallback
ToolingWrangler 4, Playwright (audit harness), npm in CI

Key Features

  • Vietnamese-slugged routes (/san-pham, /danh-muc, /gio-hang, /thanh-toan, …) and full SEO meta on every page
  • Live catalog snapshotnpm run fetch:catalog pulls D1 → src/data/*.generated.ts so the static build always carries the latest catalog
  • RAG chatbot grounded on Workers AI + Vectorize, with Gemini primary and OpenRouter fallback through Cloudflare AI Gateway
  • VietQR bank-transfer checkout generated server-side for every order
  • React 19 admin SPA mounted at /admin for catalog + order management
  • GA4 + GTM + Facebook Pixel all loaded through Partytown so analytics never block the main thread
  • Diacritic-tolerant product search — store both the original Vietnamese name and a stripped search_name, plus a JS fallback for partial matches
  • Daily crons for Vectorize embedding rebuilds and Google Merchant Center catalog sync

Architecture

src/
  pages/                  Vietnamese-slugged routes
  components/admin/       React 19 SPA mounted at /admin
  components/cart/        cart + checkout islands
  data/                   *.generated.ts (live D1 snapshot) + *.fallback.ts
  lib/                    catalog domain, view-models, sitemaps, VietQR, theme
functions/
  api/                    Cloudflare Pages Functions (admin, auth, products, orders, chat …)
  _shared/                csrf, session, rate-limit, sanitize, email, chat tools
  _middleware.ts          auth + rate-limit + security headers + CSP for /api/*
db/                       schema.sql + migration-*.sql + seed-*.sql
scripts/
  fetch-catalog.mjs       pull D1 → src/data/*.generated.ts
  build-embeddings.mjs    rebuild Vectorize index (cron)
  sync-merchant-center.mjs push catalog to Google Merchant Center (cron)
  cloudflare/worker-wrapper.js  Pages _worker.js entry
.github/workflows/        deploy.yml, preview.yml, embedding-cron.yml, gmc-sync.yml, backup-d1.yml

Implementation Highlights

  • _worker.js/ wrapper stitches Pages Functions (/api/*), the SSR worker, and R2-served media (/media/*) into a single Cloudflare Pages deployment
  • Smoke-test gate: npm run test:smoke runs astro check + astro build + verify-routes.mjs so any drift between generated routes and the expected smoke-routes.ts fails CI before deploy
  • Anonymous auth POSTs — kept auth endpoints out of the CDN cache key so a single authed POST can't poison the public response
  • Image pipeline locked to WebP for catalog + content images; the audit harness flags any non-webp asset before merge
  • Backup-D1 cron snapshots the production database to R2 nightly so we can roll back catalog or order tables independently

Role & Responsibilities

  • Full-stack ownership — Astro/React UI, Pages Functions, D1 schema + migrations, R2 media pipeline
  • Built the RAG chatbot (Workers AI + Vectorize + Gemini/OpenRouter via AI Gateway)
  • Authored the cron pipelines (catalog snapshot, embeddings rebuild, Google Merchant Center sync, D1 backup)
  • Owns deployment on Cloudflare Pages + Wrangler