Client Production Delivery

Thuý Nga Wedding & Event

End-to-end delivery of a production platform for a wedding and event decoration business in Hanoi: a public Vietnamese website plus an internal CMS and CRM that follows each deal from first enquiry to a completed event.

ASP.NET Core 10
EF Core 10 / SQL Server
Next.js 16 / React 19
TypeScript
Identity + 2FA
xUnit / Playwright
GitHub Actions

Milestones M0–M11 delivered between September and October 2026, with public go-live on 22 October 2026.

Live Site (opens in a new tab) Showcase Repository (opens in a new tab)

Production source code is private; the showcase repository is a documentation-only case study.

Overview

I delivered this platform end to end for a real client: product scope, architecture, backend and frontend implementation, security, testing, deployment, and go-live, starting from an empty repository and ending in a public production release.

My Role

Sole engineer, from requirements and architecture through implementation, testing, deployment, and go-live.

Product Scope

Public website and CMS, lead CRM, customers, events, appointments, quotations with PDF, and payment tracking.

Delivery

A foundation milestone and eleven delivery milestones, ending with security hardening, staging and user acceptance testing, business acceptance, and go-live.

How this complements H2ALL / FastLink

H2ALL / FastLink shows assigned work inside a large enterprise platform. Thuý Nga shows full ownership of a smaller system: scope, architecture, security, testing, deployment, and production delivery.

Project Objectives

  • Present the business's services and completed work in a fast, mobile-first Vietnamese website the business can maintain itself.
  • Capture quote and consultation requests safely and route them into one admin workflow.
  • Follow every deal from lead to customer, event, appointments, quotation, and payments, with an audit trail.
  • Go live with a system that is secure by default, tested end to end, and operable by a very small team.

Business Capabilities

Public Website & CMS

Services, completed projects with photo albums, guides, testimonials with recorded consent, contact, privacy policy, and SEO with structured data. Services, projects, guides, testimonials, and site content are managed from the CMS.

Lead CRM

Quote and consultation requests land in one inbox with a status workflow, an append-only activity timeline, duplicate-phone warnings, and notifications.

Customers, Events & Appointments

Explicit lead-to-customer conversion, an event lifecycle, consultations and site surveys, and a month calendar of scheduled work.

Quotations & PDF

Line items, discount, and an optional required deposit, with yearly numbering, a status workflow, and an on-demand PDF with Vietnamese typography.

Payment Tracking

Records payments already received against an accepted quotation. The remaining balance is always derived, never stored.

Administration & Audit

System and business admin roles, authenticator-app two-factor authentication, account management, and an audit log.

Deliberately out of scope: online payments, invoicing and accounting, a customer portal, and messages to customers.

Architecture

A modular monolith: one ASP.NET Core API split into Api, Core, and Infrastructure projects with a strict dependency direction, and a Next.js application serving both the public website and the admin UI. The API is served on the same origin as the web app, and notification e-mail flows through a transactional outbox.

Visitors
Public website
Administrators
CMS and CRM
Containerized Platform
Reverse Proxy
TLS termination and security headers
Next.js 16 Web App
Public site and admin UI, per-request CSP nonce
ASP.NET Core 10 API
Modular monolith on the same origin, Identity and 2FA
SQL Server
EF Core 10 with versioned migrations
E-mail Dispatcher
Transactional outbox, in-process background delivery
Media CDN
Public images and video
Bot Protection
Public forms
SMTP Relay
Notification e-mail
Analytics
Consent-gated, off at launch
Abstracted view. Hostnames, network layout, hosting provider, and operational details are intentionally omitted.
Api

HTTP host, controllers, authentication, and authorization

Core

Domain models and business rules, with no project dependencies

Infrastructure

EF Core persistence, media, PDF, bot protection, and e-mail

Technology Stack

Backend

ASP.NET Core 10 Web API
EF Core 10
ASP.NET Core Identity + 2FA
QuestPDF
MailKit

Frontend

Next.js 16 (App Router)
React 19
TypeScript
Tailwind CSS

Data & Services

SQL Server
Cloudinary (media)
Cloudflare Turnstile
GA4 (consent-gated, off at launch)

Quality & Delivery

xUnit
Node.js test runner
Playwright
GitHub Actions
Docker Compose
nginx

Backend Engineering Highlights

Correct Workflows Under Concurrency

Exactly-once lead conversion with a race-safe duplicate check, idempotent public submissions, and version checks on quotations and payments.

Money Rules on the Server

Totals, discounts, and deposits in whole đồng; payments only against an accepted quotation and never beyond its total.

Append-only History

Lead activity timelines, cancel-and-re-record payments, and an audit log with sanitized metadata.

Reliable Notifications

E-mails staged in the same transaction and delivered in the background, at least once, carrying no customer data.

Documents and Media

On-demand quotation PDFs with embedded Vietnamese fonts; public media stored without embedded metadata.

Safe Test Infrastructure

A generated database per test run behind a guard that fails closed before touching any other database.

Decisions & Trade-offs

Modular monolith, not microservices

Why: One business, related workflows, and transactions that span modules.

Trade-off: No per-module scaling; clear Api / Core / Infrastructure boundaries keep a later split possible.

Same-origin cookie authentication

Why: HttpOnly cookies, antiforgery tokens, and no cross-origin access to configure.

Trade-off: Clients must handle antiforgery tokens, and the reverse proxy must route the API path.

Server-side money, derived balances

Why: Whole-đồng amounts computed by the server; balances calculated on read, so they cannot drift.

Trade-off: A small amount of computation on every read.

Append-only payments

Why: Payments are cancelled and re-recorded instead of edited or deleted, keeping a complete history.

Trade-off: Corrections take two steps.

Transactional outbox, no broker

Why: Notification e-mails are staged with the request and delivered in the background without operating a broker.

Trade-off: At-least-once delivery; a stable message identifier mitigates duplicates.

Fail-closed configuration

Why: Outside development the API refuses to start with development switches or missing settings, and the web app refuses to build without its required settings.

Trade-off: Stricter, more explicit deployments.

Security & Reliability

Security & Privacy

  • Authenticator-app two-factor authentication, mandatory for the system administrator
  • Deny-by-default authorization, verified by an automated sweep of every endpoint
  • Antiforgery tokens, bot protection on public forms, and rate limiting
  • Content-Security-Policy with a per-request nonce and a stricter admin policy
  • Private images streamed only to signed-in administrators
  • Consent-gated analytics (off at launch), click-to-load video, and a privacy policy

Reliability & Delivery

  • Idempotent public submissions and version checks on quotations and payments
  • CI check that database migrations match the model
  • Pinned toolchain, locked restores, and NuGet / npm vulnerability audits
  • Migration and backup/restore procedures rehearsed before go-live
  • Staging with user acceptance testing and a protected production preview
  • Releases identified by exact commit, with the previous release kept for rollback
Scope of this section: it describes practices, not configuration. Thresholds, allow-lists, hostnames, and operational procedures are intentionally left out.

Testing & CI/CD

265 Backend test-project files

96 unit and 169 integration C# files, including shared test infrastructure

~1,950 xUnit test methods

Facts and theories; theories run several cases

57 Frontend unit-test files

Run with the Node.js test runner

60 Playwright specs

Desktop 1440 px and phone 375 / 360 px journeys

Test inventory at the production release: counts of test files and test methods, not executions.

  1. Step 1

    Locked restore, build, migration check, and vulnerability audit

  2. Step 2

    Unit and integration tests on a throwaway SQL Server

  3. Step 3

    Lint, typecheck, unit tests, and production build

  4. Step 4

    Playwright journeys against the real API

  5. Step 5

    Merge only on green CI for the exact commit

GitHub Actions runs on every pull request, with actions pinned to full commit SHAs and a read-only token. CI stores no secrets and performs no deployment; releasing is a separate, approved step.

Delivery & Milestones

  1. M0Platform foundation and technical spikes
  2. M1Authentication, 2FA, and admin shell
  3. M2Services and basic CMS
  4. M3Portfolio and media
  5. M4Public website and SEO foundations
  6. M5Quote requests and lead CRM
  7. M6Customers, events, appointments, and calendar
  8. M7Quotations, pricing, and PDF
  9. M8Payment tracking and remaining balance
  10. M9Notifications, e-mail, and SEO completion
  11. M10Security hardening, staging, and UAT
  12. M11Production readiness and go-live

Path to production

Security hardening, then a production-like staging environment with user acceptance testing, business acceptance by the client, and a protected preview of the production site. The public go-live followed on 22 October 2026, and a Next.js security update shipped to production the next day.

Lessons Learned

  • Out-of-scope lists matter as much as scope: writing down what each milestone would not do (for example, no payment gateway) kept delivery focused.
  • An application that refuses to start without its required settings turns a configuration checklist into an automated gate.
  • Concurrency, idempotency, and money rules are best proven against a real database rather than mocks.
  • Privacy work needs lead time: consent, data-protection procedures, and the privacy policy had to be ready before launch.
  • Development was supported by Claude Code, with independent AI-assisted technical reviews. Project decisions, manual QA, release approvals, and final acceptance remained under human ownership.
Confidentiality: the production source code is private. This case study describes product scope, architecture, and engineering practice without exposing source code, client data, credentials, or infrastructure details. The business name, brand, and website belong to the client.