Ever After
A production full-stack app built outside work.
← Back home
Production

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.

PlanningEventsGuestsVendorsFinanceTasks

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

Angular 21SignalsStandalone ComponentsDeferrable ViewsTailwind CSSTypeScript

Backend

NestJSPrisma ORMSQLitePassport.jsGoogle OAuth 2.0JWT (httpOnly)

DevOps

Nx MonorepoDocker ComposeNginxSynology NAS

Shared

TypeScript (shared types)ESLintPrettierZod (validation)