Ever After
Full-Stack Wedding Planning Platform
A production wedding planning app I built: Angular 21 frontend with Signals for fine-grained reactivity, NestJS backend with 50+ RESTful endpoints, 14 Prisma models defining the wedding domain, Google OAuth with role-based access control, and Docker Compose deployment on a Synology NAS.
At a glance
Nx monorepo with shared TypeScript types between Angular SPA and NestJS API. Event-based domain model supporting 11 wedding event types. Budget engine with real-time spend tracking. JWT httpOnly cookies for XSS-resistant auth. SQLite for zero-config persistence.
14
Prisma Models
Full relational schema
60+
Components
Angular standalone
50+
Endpoints
RESTful NestJS API
25+
Modules
NestJS backend modules
11
Event Types
Wedding event categories
10
Theme Presets
Customizable palettes
Architecture
Nx workspace with shared TypeScript types between Angular frontend and NestJS backend. Single version policy, enforced module boundaries, and unified linting.
Nx Workspace
- apps/web → Angular 21 SPA
- apps/api → NestJS API
- libs/shared-types → TypeScript interfaces
Domain Model
14 Prisma models organized across 6 domain groups — the wedding planning data model.
Planning
Events
Guests
Vendors
Finance
Tasks
Click a model to explore its fields and relationships.
Event Types
Weddings aren't one event — they're a series of events, each with different guests, vendors, and logistics.
Ceremony
The main wedding ceremony
Reception
Post-ceremony celebration and dinner
Rehearsal Dinner
Pre-wedding rehearsal gathering
Bridal Shower
Pre-wedding celebration for the couple
Bachelor/ette Party
Pre-wedding party events
Brunch
Morning-after or welcome brunch
Sangeet
Musical celebration and performances
Mehndi
Henna art ceremony
Photo Session
Dedicated photography session
Welcome Event
Guest arrival welcome gathering
After-Party
Late-night celebration
Key Technical Decisions
Signals over RxJS
Replaced RxJS BehaviorSubjects with Angular Signals for component state. Fine-grained reactivity without subscription management or Zone.js dirty checking.
Line of thinking
RxJS is powerful for async streams but overkill for synchronous UI state. Every BehaviorSubject needed manual unsubscription (or takeUntilDestroyed), and Zone.js was re-checking the entire component tree on every change. Signals give us fine-grained reactivity: only the template bindings that read a signal re-render. The code is simpler, there are no memory leaks, and computed() replaces complex combineLatest chains. RxJS is still used for HTTP calls and WebSocket streams where async operators genuinely add value.
Feature Deep Dives
Budget Engine
Real-time financial tracking with category-based allocation, vendor payment linking, and contingency reserves. Every payment updates category spend totals instantly via Angular Signals.
- Category-based budget allocation with percentage or fixed-amount splits
- Vendor payments auto-linked to budget categories with status tracking
- Configurable contingency reserve (default 10%) auto-calculated
- Real-time spend vs. allocation dashboard with overspend warnings
- Optimistic UI updates with server reconciliation on conflict
Tech Stack
Frontend
Backend
DevOps
Shared