supabase-db-model
Chuẩn hoá cách đọc/viết DB model Supabase (migrations + TS types + services) trong repo này.
When & Why to Use This Skill
This Claude skill standardizes the Supabase database development workflow by synchronizing migrations, TypeScript types, and service layers. It enforces a 'DB-first' source of truth, ensuring that database schema changes are automatically reflected in type-safe code, while providing optimized patterns for complex queries, full-text search, and relational data handling.
Use Cases
- Case 1: Synchronizing database schema changes with TypeScript types to ensure end-to-end type safety across the application.
- Case 2: Implementing standardized service layers for complex data operations, such as flattening junction tables for blog tags or handling full-text search (FTS) with GIN indexes.
- Case 3: Managing database migrations and DDL updates through a structured workflow using Supabase MCP tools like apply_migration and execute_sql.
- Case 4: Streamlining the development of advanced filtering logic, such as date range filters for admin dashboards and slug normalization for public documentation.
| name | supabase-db-model |
|---|---|
| description | Chuẩn hoá cách đọc/viết DB model Supabase (migrations + TS types + services) trong repo này. |
Mục tiêu
- Giữ source of truth ở Supabase (DB-first) và truy cập dữ liệu qua
apps/web/src/services/*-service.ts. - Dùng type-safe schema từ
apps/web/src/types/database.tskhi thao tác với Row/Insert/Update.
Nguồn sự thật trong repo
- Schema/migrations:
apps/web/supabase/migrations/*.sql - Types (generated/committed):
apps/web/src/types/database.ts - Query patterns:
- Blog:
apps/web/src/services/blog-service.ts - Docs:
apps/web/src/services/docs-service.ts
- Blog:
Type pattern (khuyến nghị)
- Row type:
Database['public']['Tables']['blog_posts']['Row']
- Insert type:
Database['public']['Tables']['blog_posts']['Insert']
- Update type:
Database['public']['Tables']['blog_posts']['Update']
Ví dụ đang dùng trong repo:
- Blog joins:
blog_posts+profiles(author) +media(cover/og) +tags(quablog_post_tags).
Query patterns quan trọng
1) Joins + flatten junction table
- Repo dùng join kiểu:
tags:blog_post_tags(tag:tags(*))
- Sau đó flatten bằng helper (xem
flattenTagstrongapps/web/src/services/blog-service.ts).
2) Full-text search (FTS)
- Blog list dùng
textSearch('search_vector', term, { type: 'websearch', config: 'simple' }). - Khi thêm field mới vào tìm kiếm, cần cập nhật:
- Migration tạo/đổi
search_vector(index GIN nếu có) - Service query (tên column phải khớp)
- Migration tạo/đổi
3) Date range filter cho admin
- Pattern trong repo: dùng
.or(...)để match cảcreated_atvàpublished_at/updated_at. - Xem
applyOrDateFiltertrongblog-service.tsvàdocs-service.ts.
4) Docs slug normalization
- Public docs dùng
slugParts.join('/')và map'' -> 'index'(xemgetPublicDocBySlugtrongdocs-service.ts). - Khi thiết kế URL docs, ưu tiên giữ quy ước
indexnày để tránh 2 nguồn truth.
Workflow khi đổi DB
- Tạo migration mới dưới
apps/web/supabase/migrations/(DDL/RLS/indexes). - Apply migration bằng Supabase MCP:
- DDL: dùng
apply_migration - Debug dữ liệu: dùng
execute_sql
- DDL: dùng
- Regenerate TypeScript types:
- Ưu tiên dùng Supabase tooling (CLI hoặc MCP
generate_typescript_types) để cập nhậtapps/web/src/types/database.ts.
- Ưu tiên dùng Supabase tooling (CLI hoặc MCP
- Cập nhật services (
apps/web/src/services/*-service.ts) và types helper nếu cần.
Lưu ý
- Không hardcode secrets/keys.
- RLS: thay đổi policy phải có migration rõ ràng.
- App Router Next.js 16: pages phải
await params/searchParams(liên quan khi query theo locale/slug).