Art Portfolio Platform
Migrated from Vue SPA to Next.js SSG/ISR. SEO improved from 72 → 100, performance score 94/100. Three-tier caching + CDN delivering blazing fast loading speeds.
FCP 2.1s → 0.8s (-62%), LCP 3.8s → 2.1s (-45%) (migration phase); final Perf 94/100, SEO 100/100.
API calls 12 → 2.6/visit (-78%), CDN hit rate 90%.

Background & Goals
- Legacy site: Vue SPA with SEO-unfriendly architecture, slow first paint, no caching; international access relied on direct browser connections, large images, high CLS.
- Goals: Search visibility (SSR/SSG/ISR), performance (Core Web Vitals all green), stable editing experience (CMS), multilingual (EN/FR/ZH), and European compliance (GDPR-friendly analytics).
Architecture
Architecture flow: Next.js (Vercel) → Strapi v5 API → Supabase (Postgres + Storage); frontend images via Next/Image + Supabase CDN; Umami Edge collects minimal data
Technical Highlights:
- •Frontend Next.js → Strapi API → Supabase Postgres/Storage; frontend images via Next/Image + Supabase CDN; Umami Edge collects minimal data.
- •Public content requires zero authentication + database RLS as fallback (even bypassing API only reads published content); Admin side uses JWT.
- •Transport layer (TLS 1.3, HSTS), domains and certificates managed by Vercel/Render/Supabase.
Results & Metrics
| 指标 | 数值 |
|---|---|
FCP -62% (migration phase) | 2.1s → 0.8s |
LCP -45% (migration phase) | 3.8s → 2.1s |
TTI -55% | 4.2s → 1.9s |
CLS -80% | 0.15 → 0.03 |
TBT -46% | 280ms → 150ms |
Bundle Size -43% | 1.2MB → 680KB |
Requests/Visit -78% | 12 → 2.6 |
CDN Hit Rate production verified | ~90% |
SEO Score Google indexed 0 → 320 pages, 1,240 organic monthly visits | 72 → 100 |
Perf Score Lighthouse (final) | 94/100 |
Email Success Rate subscription conversion +334%, zero churn | 23% → 99.7% |
API Calls backend load -78%, cost savings $15/mo | 12 → 2.6 calls |
API Contract
- Public API: Read artworks/categories/homepage; no token required (relies on RLS: read-only published content).
- Admin API: JWT (Strapi Admin), 24h expiration, no refresh token.
- RLS example (read-only published):
USING (published_at IS NOT NULL); media files public read policy. - Rate limiting: IP-level rate limiting on public endpoints.
Data Model
- Core ER: categories ⇄ products (artworks) ⇄ files (media);
- Strapi v5 Document Model:
Samedocument_id→ Draft (published_at=NULL) + Published (published_at!=NULL)
Frontend reads only Published (zero auth + RLS fallback) - Technical Highlights:
Admin edits Draft → Click Publish → Auto-sync to Published
Database RLS Policy enforced: Even bypassing API only reads published content
Key Code & Engineering Practices
Subscription Service (Idempotency & State Machine)
Migrated from SMTP to Mailgun HTTP API; state machine pending → verified → unsubscribed + idempotency handling; delivery success rate reached ≈99.7%.
services/subscriptionService.tsProduction Data Migration Script
SQLite → Supabase (Postgres + Storage), four phases: "pre-check → compatibility → atomic migration → validation", media file concurrency optimization: serial upload 2h → concurrent upload 20min (83% improvement). Total migration time: 2.5 hours (319 products + 905 media + 888 relations).
scripts/migrate-to-supabase.tsFrontend Configuration Center + Memory Cache
Unified environment variables, application-level caching, implementing "three-tier caching".
Three-tier cache hit rate breakdown:
- Layer 1 (Build SSG): 60% hit rate (first visit)
- Layer 2 (ISR Edge): 30% hit rate (re-visit within 1 hour)
- Layer 3 (Memory): 10% hit rate (category/settings API)
→ Total hit rate 90%, API calls 12 → 2.6 (-78%)
lib/configService.tsSecurity & Privacy
- Data minimization: No collection of names/phone numbers; Umami replaces third-party tracking; categorized cookie consent.
- At-rest/in-transit encryption: Postgres/S3 encryption, TLS1.3, site-wide HSTS.
- Retention & access control: Access logs 30 days; Public/Authenticated/Admin permission definitions.
Architecture Decision Records (ADR)
- SPA → Next.js App Router (SSG/ISR): SEO & performance first.
- Public content zero-auth + RLS: Cleaner frontend, security fallback in DB.
- Supabase Storage (public bucket + CDN): Balance of cost/complexity/latency.
My Role
- · Architecture Design: Defined Vue → Next.js migration path, SSG/ISR strategy
- · Strapi Integration: Content Types design, i18n configuration, permission policies
- · Performance Optimization: Three-tier caching, image optimization, Bundle analysis & optimization
- · Data Migration: Wrote migration scripts, SQLite → Supabase (Postgres + Storage)
- · GDPR Compliance: Umami integration, Cookie policies, data minimization
- 💡 Complexity: Solo responsibility for frontend (68 files) + backend (42 files) + DevOps + data migration
Next Steps
- Integrate Sitemap + RSS (improve crawl efficiency)
- Add Edge caching and regional routing (EU/US nodes)
- Implement semantic search for artwork filtering (vector search, technology TBD)