# Project Research Summary

**Project:** Teressa Copeland Homes
**Domain:** Real estate agent marketing site + custom PDF document signing portal (Utah/WFRMLS)
**Researched:** 2026-03-19
**Confidence:** HIGH

## Executive Summary

This is a dual-product build: a public real estate marketing site for a solo Utah agent, and a private document-signing portal that replaces per-month third-party tools (DocuSign, HelloSign) with a fully branded, custom implementation. Research across all four domains converges on a single-repo Next.js 15 application deployed to Vercel with a Neon PostgreSQL database and Vercel Blob storage for PDFs. The stack is unambiguous: `pdfjs-dist` for browser PDF rendering, `@pdfme/pdf-lib` (the maintained fork) for server-side PDF modification, `signature_pad` for canvas signature capture, `better-auth` for agent authentication, and `resend` for email delivery of signing links. This combination is well-documented, actively maintained, and sized exactly right for a solo-agent workflow — no enterprise licensing, no per-user cost, and full brand control throughout.

The recommended architecture cleanly separates two subsystems that share only the Next.js shell: the public marketing site (listings, bio, contact) and the protected agent portal (clients, documents, signing requests). These can be built in parallel after the foundation is in place and are only loosely coupled — the listings page has no dependency on the signing flow, and vice versa. The five-stage PDF pipeline (import → parse fields → fill text → send for signing → embed signature) maps directly to a sequential build order where each stage unblocks the next. The architecture research prescribes a 7-phase build order that aligns exactly with this dependency chain.

The most serious risks in this domain are legal, not technical. A custom e-signature implementation that lacks a tamper-evident PDF hash, an incomplete audit trail, or replayable signing links is legally indefensible under ESIGN/UETA regardless of how well the rest of the app works. Pitfalls research is unambiguous: audit logging and one-time token enforcement must be built in from the first signing ceremony — they cannot be retrofitted. A second cluster of risk sits in the WFRMLS integration: scraping the utahrealestate.com forms library violates Terms of Service (the platform partners with SkySlope; no public API exists for forms), and displaying IDX listing data without required broker attribution and NAR-mandated disclaimer text risks fines and loss of MLS access. Both risks are avoidable with correct design decisions made before code is written.

## Key Findings

### Recommended Stack

The stack is cohesive and all components are current-stable. Next.js 15.5.x (not 16 — too many breaking changes just landed) with React 19 provides the full-stack framework, App Router route groups for clean public/agent separation, and Server Components for the listings page without client-side JavaScript. Neon PostgreSQL with Prisma 6.x is the data layer — serverless-compatible, branches per PR, and generous free tier. Authentication uses `better-auth` 1.5.x (Auth.js/NextAuth is merging with better-auth and remains in beta; Clerk has per-MAU pricing that makes no sense for a single agent). PDF processing requires three distinct libraries that serve non-overlapping roles: `pdfjs-dist` for browser rendering and field detection (cannot modify PDFs), `@pdfme/pdf-lib` for server-side modification and signature embedding (cannot render to screen), and `signature_pad` for canvas capture. The original `pdf-lib` is unmaintained (4 years since last publish) — use the `@pdfme/pdf-lib` fork exclusively.

**Core technologies:**
- **Next.js 15.5.x**: Full-stack framework — App Router, Server Components, API routes in one repo; Vercel-native; skip v16 until ecosystem stabilizes
- **React 19**: Ships with Next.js 15; Server Components and form actions stable
- **TypeScript 5.x**: Required; all major libraries ship full types
- **Neon PostgreSQL + Prisma 6.x**: Serverless-compatible DB; best-in-class DX for TypeScript; Vercel Marketplace integration
- **better-auth 1.5.x**: No per-MAU cost; built-in rate limiting; first-class Next.js App Router support
- **pdfjs-dist 5.5.x**: Browser-side PDF rendering and AcroForm field detection only
- **@pdfme/pdf-lib 5.5.x**: Server-side PDF modification — fill fields, embed signature PNG, flatten; actively maintained fork
- **signature_pad 5.1.3**: Canvas signature capture; Bezier smoothing; touch-normalized; use directly (not the alpha React wrapper)
- **resend + @react-email/components**: Transactional email for signing links; 3k/month free tier; React email templates
- **@vercel/blob**: Zero-config PDF storage for Vercel; S3-backed; abstract behind `storage.ts` to allow future swap
- **Playwright**: Required for utahrealestate.com forms (if used); run via separate service or Browserless.io — not inline in Vercel serverless
- **Tailwind CSS v4 + shadcn/ui**: Styling; Tailwind v4 is CSS-native, no config file required

**Critical version note:** Do NOT use `next@16` — breaking changes (async APIs, middleware renamed to proxy, edge runtime dropped) make it incompatible with the ecosystem today. Use `next@15.5.x` and revisit in 6-12 months.

### Expected Features

Research identifies a clear MVP boundary. The signing portal is the novel differentiator — all the marketing site features are table stakes for any professional real estate presence. The key UX insight from feature research: no client account creation, ever. The signing link token is the client's identity. Every friction point between "email received" and "signature captured" is an abandonment driver.

**Must have for v1 launch (P1):**
- Marketing site: hero with agent photo, bio, contact form, testimonials
- Active listings display from WFRMLS (with full IDX compliance: broker attribution, disclaimer text, last-updated timestamp)
- Agent login (better-auth, credentials)
- Client management: create/view clients with name and email
- PDF upload and browser rendering (pdfjs-dist + react-pdf)
- Signature field placement UI: drag-and-drop on PDF canvas with coordinate storage in PDF user space
- Email delivery of unique, tokenized signing link (resend)
- Token-based anonymous client signing page: no account, no login
- Canvas signature capture (signature_pad) — mobile-first, touch-action:none, iOS Safari tested
- Audit trail: IP, timestamp, user-agent, consent acknowledgment — all server-side timestamps
- PDF signature embed + form flatten with fonts embedded before flattening (@pdfme/pdf-lib)
- Tamper-evident PDF hash: SHA-256 of final signed PDF bytes stored in DB
- One-time signing token enforcement: used_at column, DB transaction, 72-hour TTL
- Signed document storage (Vercel Blob, private ACLs, presigned URLs only)
- Agent dashboard: document status at a glance (Draft / Sent / Viewed / Signed)

**Should have, add after v1 (P2):**
- Forms library import from utahrealestate.com — add only as manual agent upload, not scraping
- Heuristic AcroForm field detection on Utah standard forms — manual placement fallback always present
- Document view/open tracking (link opened audit event)
- Signed document confirmation email to client
- Multiple field types: initials, auto-date, checkbox, text inputs
- Neighborhood guide / SEO content pages

**Defer to v2+ (P3):**
- Automated unsigned-document reminder system (requires scheduling infrastructure)
- Client portal with document history (requires client accounts — explicitly an anti-feature in v1)
- Multi-agent / brokerage support (role/permissions model doubles auth complexity)
- Bulk document send
- Native mobile app (responsive web signing works; 50%+ of e-signatures happen on mobile web)

**Anti-features to avoid entirely:**
- Scraping utahrealestate.com forms library (ToS violation; use manual upload)
- DocuSign/HelloSign integration (monthly cost, third-party branding — defeats the purpose)
- In-app PDF content editing (real estate contracts have legally mandated language; editing creates liability)
- WebSockets for signing (one-shot action, not a live session)
- Client account creation for signing (friction kills completion rates)

### Architecture Approach

The system is a single Next.js monorepo with two distinct route groups: `(public)` for the unauthenticated marketing site and `(agent)` for the protected portal. These share the Prisma/Neon data layer and Vercel Blob storage but have no UI coupling. The PDF pipeline is entirely server-side (API routes / Server Actions) except for browser rendering and signature capture, which require Client Components loaded with `dynamic(() => import(...), { ssr: false })`. Authentication uses three defense-in-depth layers — edge middleware, layout Server Component, and per-route handler — because the CVE-2025-29927 middleware bypass (disclosed March 2025) demonstrated that middleware alone is not sufficient. The signing flow uses JWT tokens (HMAC-SHA256) stored server-side with one-time enforcement via a `used_at` column, providing both stateless verification and replay protection.

**Major components and responsibilities:**

1. **`middleware.ts`** — Edge auth gate for `/agent/*`; redirects to login; NOT the only auth layer (CVE-2025-29927 requires defense in depth)
2. **`(agent)/layout.tsx`** — Server Component second auth layer; calls `verifySession()` on every render
3. **`lib/pdf/parse.ts`** — pdfjs-dist server-side: extracts AcroForm field names, types, and bounding boxes from PDF bytes
4. **`lib/pdf/fill.ts`** — @pdfme/pdf-lib server-side: writes agent-supplied text into named form fields; embeds fonts before flattening
5. **`lib/pdf/sign.ts`** — @pdfme/pdf-lib server-side: embeds signature PNG at stored coordinates; flattens and seals the form; computes SHA-256 hash
6. **`components/agent/PDFFieldMapper.tsx`** — Client Component: renders PDF page via canvas; drag-to-define signature zones; converts viewport coordinates to PDF user space (origin bottom-left) before storing
7. **`components/sign/SignatureCanvas.tsx`** — Client Component: signature_pad with touch-action:none; exports PNG for submission
8. **`app/sign/[token]/page.tsx`** — Public signing page: validates JWT, streams prepared PDF, renders field overlays, submits canvas PNG
9. **`lib/wfrmls/client.ts`** — WFRMLS RESO OData client with ISR revalidate=3600 for listings
10. **`lib/storage/s3.ts`** — Vercel Blob abstraction: upload, download, presigned URL (5-minute TTL); PDFs never served with public ACLs

**Database schema highlights:** `User` → `Client` → `SigningRequest` → `SignatureAuditLog` chain. `Document` stores the raw PDF template (reusable across multiple `SigningRequest`s). `SigningRequest` holds `fieldValues`, `signatureFields` (coordinates in PDF space), `preparedS3Key`, `signedS3Key`, `token`, `tokenJti`, `usedAt`, and status enum (DRAFT/SENT/VIEWED/SIGNED/EXPIRED/CANCELLED). `SignatureAuditLog` is append-only and records every ceremony event with server-side timestamps.

**PDF coordinate conversion is mandatory:** Browser canvas coordinates (origin top-left, Y down) must be converted to PDF user space (origin bottom-left, Y up) using `viewport.convertToPdfPoint(x, y)` from pdfjs-dist before storage. This conversion must be unit-tested against actual Utah real estate forms before the field placement UI ships.

### Critical Pitfalls

1. **No tamper-evident PDF hash** — Compute SHA-256 of the complete signed PDF bytes immediately after embedding the signature, before storing. Store the hash in `SigningRequest`. This is the difference between a legally defensible document and "a drawing on a page."

2. **Incomplete audit trail** — Log six ceremony events server-side: document prepared, email sent, link opened (with IP/UA/timestamp), document viewed, signature submitted, final PDF hash computed. Timestamps must be server-side — client-reported timestamps are legally worthless. This must be wired in before the first signing ceremony, not added later.

3. **Replayable signing token** — Signing tokens must have a `used_at` column set atomically on successful submission (DB transaction to prevent race conditions). After use, the link must return "already signed" — never the canvas. 72-hour TTL is appropriate for real estate (clients don't check email instantly; 15-minute magic-link windows are too short).

4. **PDF coordinate system mismatch** — PDF user space uses bottom-left origin with Y increasing upward; browser canvas uses top-left with Y downward. Embedding a signature without the conversion inverts the Y position. Write a coordinate conversion unit test against a real Utah purchase agreement form before building the drag-and-drop UI. Also handle page rotation (`Rotate` key in PDF) — Utah forms may be rotated 90 degrees.

5. **utahrealestate.com forms scraping violates ToS** — The platform partners with SkySlope and has no public forms API. Storing Teressa's credentials to automate downloads violates the WFRMLS data licensing agreement. Use manual PDF upload as the document source. State-approved Utah DRE forms at commerce.utah.gov are public domain and can be embedded directly.

6. **IDX compliance violations** — Every listing page (card and detail) must display: listing broker/office name (`ListOfficeName`), WFRMLS disclaimer text verbatim, last-updated timestamp from the feed, and buyer's agent compensation disclosure per 2024 NAR settlement. Missing any of these risks fines up to $15,000 and loss of MLS access. Treat these as acceptance criteria, not post-launch polish.

7. **PDF font flattening failure** — AcroForm fields reference fonts by name (e.g., "Helvetica"). On Vercel serverless, no system fonts are installed. Calling `form.flatten()` without first embedding fonts produces blank text fields in the downloaded PDF. Explicitly embed standard fonts from pdf-lib's built-in set on every form field before flattening. Validate in production environment, not just local Mac with system fonts.

8. **Mobile canvas scrolling instead of signing** — Without `touch-action: none` on the canvas element, iOS Safari and Android Chrome intercept touch gestures as page scroll. The client tries to sign and the page scrolls instead. This must be tested on physical devices before any client is sent a signing link.

## Implications for Roadmap

Based on the dependency chain identified in architecture research and the feature priority matrix from feature research, the natural build order is 7 phases:

### Phase 1: Foundation
**Rationale:** Everything else depends on this. Database schema, auth system, and storage infrastructure must exist before any feature can be built. Auth has a well-documented security pattern (three-layer defense-in-depth due to CVE-2025-29927) that must be established upfront — retrofitting auth is expensive.
**Delivers:** Working Next.js project, Prisma schema + Neon DB, Vercel Blob bucket, better-auth credentials login, middleware + layout guard, agent can log in and reach a blank dashboard.
**Addresses:** Agent login (P1 feature), tamper-resistant auth architecture.
**Avoids:** Middleware-only auth bypass (CVE-2025-29927 defense-in-depth established from day one).
**Research flag:** None needed — well-documented patterns for all components.

### Phase 2: Public Marketing Site
**Rationale:** Independent of the document workflow; provides immediate business value; unblocks IDX integration testing early. Can be built by a different person in parallel with Phase 3 if needed.
**Delivers:** Public-facing site with hero, bio, contact form, and WFRMLS listings display with full IDX compliance (broker attribution, disclaimer, last-updated, NAR 2024 compensation disclosure).
**Addresses:** Hero/bio/contact (P1), listings display (P1), IDX compliance (legal requirement), delta-sync listings refresh.
**Avoids:** Stale off-market listings (hourly delta sync with `ModificationTimestamp` filter); IDX attribution violations (treated as acceptance criteria, not polish).
**Research flag:** WFRMLS RESO API vendor enrollment takes 2-4 weeks — start this process immediately, in parallel with Phase 1. Do not block Phase 2 on this; build with mock data while approval is pending.

### Phase 3: Agent Portal Shell
**Rationale:** Client management and the agent dashboard are prerequisites for the document workflow. These are straightforward CRUD operations with standard patterns.
**Delivers:** Agent dashboard (skeleton), client list + create/edit, agent login page polish, navigation shell.
**Addresses:** Client management (P1), document status dashboard (P1).
**Avoids:** No pitfalls specific to this phase — standard CRUD patterns.
**Research flag:** None needed — well-documented patterns.

### Phase 4: PDF Ingest and Storage
**Rationale:** Must exist before field mapping UI can be built. The storage abstraction and PDF parsing pipeline are the lowest layer of the document workflow.
**Delivers:** PDF upload (manual agent upload — no scraping), Vercel Blob storage pipeline (original/prepared/signed versions), pdfjs-dist AcroForm field extraction, document create + detail pages.
**Addresses:** PDF upload + rendering (P1), signed document storage (P1).
**Avoids:** Local filesystem storage (serverless ephemeral filesystem); utahrealestate.com scraping (manual upload only, no credentials stored, no headless browser automation in core app); PDF coordinate detection tested with actual Utah forms.
**Research flag:** May need deeper research on pdfjs-dist Node.js legacy build for server-side parsing — uses `pdfjs-dist/legacy/build/pdf.mjs` without a worker, which is distinct from the browser build.

### Phase 5: PDF Fill and Field Mapping
**Rationale:** Depends on Phase 4 (storage + parse infrastructure). The field mapper UI and the fill API are the agent's core document preparation workflow.
**Delivers:** PDFFieldMapper.tsx (drag-to-place signature zones on PDF canvas), coordinate conversion from viewport space to PDF user space with unit tests, @pdfme/pdf-lib fill API (text fields, font embedding before flatten), document editor form.
**Addresses:** Signature field placement UI (P1), agent-fills-then-client-signs workflow (differentiator).
**Avoids:** PDF coordinate mismatch (unit-tested against actual Utah purchase agreement form before UI ships); font flattening failure (fonts embedded explicitly; tested in production serverless environment); heuristic-only detection (manual placement fallback is the primary flow; auto-detect is an enhancement).
**Research flag:** Research the specific pdfjs-dist `viewport.convertToPdfPoint()` API and pdf-lib `StandardFonts` embedding before implementation — these are narrow but critical APIs.

### Phase 6: Signing Flow — End to End
**Rationale:** The highest-complexity phase; depends on all previous phases. Contains all the legally critical components. Should be built as a complete vertical slice in one phase to ensure the audit trail is woven through from start to finish.
**Delivers:** JWT token generation (HMAC-SHA256, 72-hour TTL, one-time enforcement with `used_at` DB column), resend email delivery, `/sign/[token]` public signing page, SignatureCanvas.tsx (mobile-first, touch-action:none, iOS Safari + Android Chrome tested on physical devices), @pdfme/pdf-lib signature PNG embed, SHA-256 hash of final signed PDF, complete SignatureAuditLog (6 ceremony events with server-side timestamps), one-time token invalidation with race-condition-safe DB transaction, "already signed" page for expired/used tokens.
**Addresses:** Email delivery (P1), client signing page (P1), canvas capture (P1), audit trail (P1), signed document storage (P1), tamper-evident hash (P1).
**Avoids:** Replayable signing tokens; incomplete audit trail; mobile canvas scroll-instead-of-sign; blank-canvas submission; font flattening blank text; unsigned PDF served publicly.
**Research flag:** This phase warrants a `/gsd:research-phase` — the intersection of JWT one-time enforcement, PDF hash storage, ESIGN/UETA audit requirements, and mobile touch handling has enough edge cases that a focused spike before implementation reduces rework risk.

### Phase 7: Audit Trail, Status Tracking, and Download
**Rationale:** Completes the agent-facing visibility layer. The underlying data is already being written in Phase 6; this phase surfaces it in the UI.
**Delivers:** Document status tracking in agent dashboard (Draft/Sent/Viewed/Signed with last-activity timestamp), presigned Vercel Blob URLs for agent PDF download (5-minute TTL, authenticated route only), confirmation screen for client after signing, optional signed document email to client.
**Addresses:** Agent dashboard status (P1 polish), signed document retrieval (P1), document view tracking (P2).
**Avoids:** Signed PDFs accessible via guessable URL (all downloads gated behind authenticated presigned URLs).
**Research flag:** None needed — well-documented patterns; the audit data infrastructure is already in place from Phase 6.

### Phase Ordering Rationale

- **Foundation first (Phase 1):** Auth, DB, and storage have zero optional dependencies. Every subsequent phase builds on these.
- **Public site early (Phase 2):** Independent of the signing workflow; provides immediate value and allows WFRMLS API approval process to complete while portal phases are underway. The 2-4 week vendor enrollment timeline makes early start critical.
- **Portal CRUD before PDF (Phase 3):** Clients and documents are the entities that the PDF pipeline operates on. Establishing the data model and basic CRUD before building the complex pipeline reduces schema churn.
- **Storage before fill before sign (Phases 4-6):** Each phase adds one layer of the PDF pipeline. Building them in dependency order means each phase can ship independently and be tested in isolation.
- **Audit/download last (Phase 7):** The underlying data is written by Phase 6. Phase 7 is surfacing and visibility only — no new data model needed.
- **Scraping architecture decision made before Phase 4:** The decision to use manual upload (no utahrealestate.com scraping) must be explicit in Phase 4 so no scraping infrastructure is ever built.

### Research Flags

**Needs `/gsd:research-phase` during planning:**
- **Phase 6 (Signing Flow):** Legal compliance intersection (ESIGN/UETA audit requirements + JWT one-time enforcement + PDF hash + mobile touch) has enough edge cases and gotchas that a pre-implementation research spike is warranted.
- **Phase 2 (Listings):** WFRMLS vendor enrollment process and exact IDX compliance requirements (disclaimer text, 2024 NAR settlement fields) should be confirmed with WFRMLS directly before the listings UI is built — the requirements change with NAR policy updates.

**Standard patterns (skip research-phase):**
- **Phase 1 (Foundation):** Next.js + Prisma + better-auth + Vercel Blob are all well-documented with official guides.
- **Phase 3 (Portal Shell):** Standard Next.js CRUD patterns; no novel integration.
- **Phase 7 (Audit/Status):** The data model is established; surfacing it is standard UI work.

## Confidence Assessment

| Area | Confidence | Notes |
|------|------------|-------|
| Stack | HIGH | All library versions verified via npm. next@15.5 vs 16 verified against official upgrade guide. pdf-lib unmaintained status confirmed (npm publish date). @pdfme/pdf-lib fork activity confirmed. better-auth + NextAuth merge confirmed via GitHub discussion. |
| Features | HIGH | Feature list cross-referenced against multiple industry sources (DocuSign, HelloSign, SkySlope/Authentisign competitor analysis). ESIGN/UETA requirements sourced from legal and engineering references. Utah-specific requirements sourced from Utah DRE and WFRMLS. |
| Architecture | HIGH | CVE-2025-29927 middleware bypass is a real, documented vulnerability (Vercel postmortem + ProjectDiscovery analysis). PDF coordinate system documented by multiple sources. Build order derived from dependency analysis, not assumption. |
| Pitfalls | HIGH | Pitfalls sourced from court cases (e-signature audit trail failures), WFRMLS vendor FAQ (ToS prohibition on scraping), NAR IDX policy statement 7.58 (attribution requirements), and confirmed GitHub issues (pdf-lib coordinate bugs, font flattening). |

**Overall confidence:** HIGH across all research areas. Sources are primary (official docs, official policies, CVE disclosures) with consistent cross-referencing. The main area of uncertainty is not technical but logistical: WFRMLS vendor enrollment timeline (2-4 weeks, outside developer control).

### Gaps to Address

- **WFRMLS vendor enrollment timeline:** The RESO OData API requires a vendor contract, background check, and compliance review — 2-4 weeks. Start this process on day one. Build the listings page with mock data or a dev-environment token while waiting. Do not block Phase 2 on this.

- **Exact IDX disclaimer text:** WFRMLS provides required disclaimer text that must appear on every listing page. This text changes with NAR policy updates (2024 settlement changed required fields). Obtain the current required text directly from WFRMLS before the listings feature ships — do not copy from another agent's site.

- **Which Utah standard forms Teressa uses most frequently:** The manual upload workflow (replacing planned scraping) needs a curated set of base forms pre-loaded. Teressa should identify the 5-10 forms she uses in 90% of transactions so they can be manually uploaded and stored as reusable document templates in the app. This is a product/content decision, not a technical one.

- **Playwright deployment strategy (if forms import is added in v1.x):** Vercel serverless functions cannot run a full Playwright browser due to size limits. If the forms library import feature is added after v1, the Playwright scraping job must run on a separate service (Railway, Render, or a $5/month VPS with Browserless.io). This architecture decision must be made before any scraping code is written — and the ToS decision must be re-evaluated at that time.

- **SPF/DKIM/DMARC for teressacopelandhomes.com:** Signing link emails sent from an unverified sender domain will go to spam. DNS records must be configured before any signing link is sent to a real client. This is a DNS/infrastructure task, not a code task — it must be in the Phase 6 acceptance criteria.

## Sources

### Primary (HIGH confidence)

- [Next.js 15.5 Release Notes](https://nextjs.org/blog/next-15-5) — framework version and stable features
- [Next.js 16 Upgrade Guide](https://nextjs.org/docs/app/guides/upgrading/version-16) — breaking changes confirming 15 is correct choice
- [CVE-2025-29927 — Next.js Middleware Bypass (Vercel)](https://nextjs.org/blog/cve-2025-29927) — middleware auth bypass requiring defense-in-depth
- [@pdfme/pdf-lib npm page](https://www.npmjs.com/package/@pdfme/pdf-lib) — v5.5.8, active maintenance confirmed
- [pdfjs-dist npm](https://www.npmjs.com/package/pdfjs-dist) — v5.5.207 current
- [signature_pad npm](https://www.npmjs.com/package/signature_pad) — v5.1.3
- [better-auth npm](https://www.npmjs.com/package/better-auth) — v1.5.5; Auth.js merge confirmed
- [UtahRealEstate.com Vendor Data Services](https://vendor.utahrealestate.com/) — RESO OData API and forms ToS confirmed
- [WFRMLS RESO OData API Examples](https://www.reso.org/web-api-examples/mls/utah-mls/) — API field names and query syntax
- [NAR IDX Policy Statement 7.58](https://www.nar.realtor/handbook-on-multiple-listing-policy/advertising-print-and-electronic-section-1-internet-data-exchange-idx-policy-policy-statement-7-58) — listing attribution requirements
- [ESIGN/UETA Audit Trail Schema — Anvil Engineering](https://www.useanvil.com/blog/engineering/e-signature-audit-trail-schema-events-json-checklist/) — legal audit requirements
- [pdf-lib Field Coordinates Issue — GitHub #602](https://github.com/Hopding/pdf-lib/issues/602) — coordinate API gap confirmed
- [Utah DRE State-Approved Forms](https://commerce.utah.gov/realestate/real-estate/forms/state-approved/) — public domain forms source
- [Vercel Blob documentation](https://vercel.com/docs/vercel-blob) — storage strategy confirmed
- [Prisma 6.19.0 announcement](https://www.prisma.io/blog/announcing-prisma-6-19-0) — version confirmed
- [Neon + Vercel integration](https://vercel.com/marketplace/neon) — serverless DB strategy

### Secondary (MEDIUM confidence)

- [NextAuth vs Clerk vs better-auth comparison (supastarter)](https://supastarter.dev/blog/better-auth-vs-nextauth-vs-clerk) — auth selection rationale (third-party analysis, but findings align with primary sources)
- [JavaScript PDF Libraries Comparison 2025 (Nutrient)](https://www.nutrient.io/blog/javascript-pdf-libraries/) — PDF library selection (vendor-written but technically accurate)
- [MLS Listing Data Freshness — MLSImport](https://mlsimport.com/fix-outdated-listings-on-your-wordpress-real-estate-site/) — delta sync approach
- [Playwright vs Puppeteer 2025 (BrowserStack)](https://www.browserstack.com/guide/playwright-vs-puppeteer) — scraping tool selection

### Tertiary (LOW confidence — validate during implementation)

- [E-Signature UX Best Practices (various vendors)](https://www.esignglobal.com/blog/best-practices-embedded-signing-user-experience-ux) — UX recommendations sourced from vendor blogs; general patterns are sound but specific metrics need validation against real user behavior
- WFRMLS exact required disclaimer text — must be obtained directly from WFRMLS; text changes with NAR policy and cannot be reliably sourced from third parties

---
*Research completed: 2026-03-19*
*Ready for roadmap: yes*
