Part 2 of 3 in the Mes Recettes series: Part 1 – Overview · Part 3 – Testing & Delivery | 🇫🇷 Version
Layered View
While early iterations keep things lean, the design leans toward a clean-ish architecture:
Component Composition
App.razor
→ MainLayout
→ page components (Recipes.razor
, Books.razor
, Authors.razor
) with dialog components for CRUD.
Benefits:
- Shared layout styling
- Dialog-based create/edit flows (fast perceived performance)
- Room to inject cross-cutting concerns later (loading, notifications)
Data Modeling Strategy
Direct table mapping via attributes:
Concept | Table | Relationship |
---|---|---|
Author | authors |
M:N with Books |
Book | books |
1:N Recipes, M:N Authors |
Recipe | recettes |
Optional Book FK |
BookAuthor | books_authors |
Junction |
Mermaid ER (simplified):
Validation Approach
- DataAnnotations enforce UI + server consistency.
- Unit tests assert boundaries (e.g., rating range).
- Future: FluentValidation layer if rules become contextual.
Patterns Documented (Future Hardening)
Pattern | Why | When to Activate |
---|---|---|
Repository | Swap storage, mock easier | When domain logic grows |
Unit of Work | Group transactions | If multi-entity changes need ACID boundaries |
Caching Decorator | Reduce duplicate reads | After identifying hot paths |
Specification | Complex querying | When queries become conditional & repetitive |
Example: Repository (Deferred)
public class SupabaseRepository<T> : IRepository<T> where T : BaseModel, new()
{
private readonly SupabaseClient _client;
public async Task<List<T>> GetAllAsync() =>
(await _client.From<T>().Get()).Models ?? new();
}
Not activated yet to avoid premature abstraction.
Real-Time & Rehydration
Supabase Realtime is pre-enabled (AutoConnectRealtime = true
). Once recipe channels are subscribed:
- Listen to
INSERT/UPDATE/DELETE
- Apply optimistic UI updates
- Optionally reconcile after silent refetch
Extensibility Points
Extension | Hook |
---|---|
Offline mode | Service worker / local storage caching |
Search | PostgreSQL full-text search + index |
Theming | MudBlazor palette service |
Audit logging | Database triggers → Append-only audit table |
Analytics | Minimal event bus (in-memory → remote sink) |
Trade-Offs
Decision | Upside | Downside |
---|---|---|
Direct model → table mapping | Simplicity, speed | Coupling to schema |
Minimal service layer early | Fast iteration | Harder to inject cross-cutting concerns later |
Supabase BaaS | Auth + Realtime + DB packaged | Vendor feature surface sets constraints |
WASM-only (no server) | CDN deploy, low hosting cost | Larger initial payload, no server prerender |
Migration Strategy (If Needed)
- Introduce Server (ASP.NET) for prerender + protected APIs.
- Carve out domain-specific service boundaries.
- Add message broker if collaboration logic grows (Redis / Azure Service Bus).
- Gradually move from direct Supabase client usage in UI to mediated services.
Checklist for Future You
- Add RLS policies (enforce ownership)
- Implement repository/caching only when metrics show need
- Introduce feature flags (simple JSON-driven) before major experiments
- Add DB schema drift tracking (e.g., pg_dump + diff in CI)
- Track bundle size budget (target < 2 MB compressed)
Source: https://github.com/mongeon/RecettesIndex