← All documents

Implementation spec · As-built audit — updated after every module

Every screen in the build, checked against one rule: nothing hardcoded, nothing faked.

Every page in this app was read line-by-line, once, in one pass — not summarized from memory. For each one: what data it actually reads (real fixture, real computed value, or a live external call), what's genuinely wired up versus decorative, and where the two disagree. Settings' real gaps got fixed the same pass; the Client Portal got built new. Everything found outside those two is listed here as an open punch list, not silently patched — this document is the source of truth for what "done" actually means on this build, module by module.

closingboss.io/docs/implementation-spec
00 — Scope & headline numbers

Nine parallel reads, one rule applied consistently everywhere.

Every route in the app — the public site, the agent dashboard, all six CRM modules, the four-part Marketing engine, Insight, all nine Settings pages, and the new Client Portal — was audited against three questions: does every displayed fact trace to real fixture data or a real computed value (never a frozen literal that should be dynamic)? Does every button/form/toggle actually change real state (never a silent no-op)? And where a real capability genuinely can't exist yet — no backend, no auth, no live payment processor — does the page say so, instead of pretending?

Fixed this pass

  • All 9 Settings pages — most were fully inert (native-reload forms, dead buttons, a theme picker that couldn't visibly change)
  • Client Portal (new) — /portal/[token], States A & B
  • A ~40-error dead crm/ directory deleted — orphaned pre-respec pages nothing linked to, found while getting a clean build

Found, still open

  • 2 of the public site's 3 lead-capture forms are completely non-functional (§03 — the highest-priority item in this document)
  • A handful of real bugs in Spotlight, Tasks, and the Marketing engine (§04–06)
  • Tracking Links' entire "+ Create link" flow is decorative (§07)
Nothing in "still open" was silently patched. Fixing all of it in the same pass as Settings would have meant editing public-facing lead-capture forms and the live Spotlight/SimplyRETS integration without a checkpoint — the two riskiest surfaces in the app to get wrong quietly. Every item below has a file, a line, and a concrete fix already worked out; none of it is a mystery, it's a sequencing choice.
01 — Settings

Every page now reads real data and every control does something real.

This was the worst-off area found anywhere in the app — not under-featured, actually broken. The theme picker used an uncontrolled defaultChecked radio with no state, so clicking a different swatch never visibly changed the selection. The About form, the domain Add form, and the account Login form all had no onSubmit at all, so clicking Save triggered a native browser form submission — a full page reload that silently discarded whatever was typed. Several buttons (logo upload, photo replace, copy link, testimonial toggle) had no onClick whatsoever.

Two genuinely un-buildable actions — QR code download, invoice PDF download — get honest click feedback (a real, disclosed "not wired in this wireframe" response) instead of either silence or a fabricated file. tsc, lint, and a full production build all pass clean.

02 — Client Portal (new)

The first client-facing surface in the app — real data, one deliberately deferred state.

Lives at /portal/[token], entirely outside the agent-facing (app) shell — no left rail, no internal nav. A real portalToken field resolves each link to a real contact; it's a real lookup, explicitly not a claim of real security (no cryptographic randomness, no expiration, no auth system anywhere in this codebase to back one).

Built — States A & B

  • Milestone stepper off the real TRANSACTION_CHECKLISTS data
  • A genuine second trigger path for document signing — the client's own click runs the exact same state transition as the agent's "Mark as signed"
  • Real favorited listings, real listing-alert enrollment with a live matching count
  • A "submit a question" field that appends a real inbound message to the contact's actual thread

Deliberately not built — State C

  • The reference spec's multi-transaction switcher assumes a contact can have two concurrent deals
  • This entire app is built on Contact = Deal, strictly 1:1 — Pipeline, Documents, Calendar, and Marketing all depend on that
  • Faking a second deal onto a real contact to demo this would misrepresent real data; a real fix touches Pipeline too — its own future scoping conversation, not a Portal-sized change
03 — Public site & lead capture

Two of the three forms whose entire job is capturing a lead do not work.

Highest-priority open item in this document. /site/valuation and both forms on /site/contact (send a message, schedule a consultation) have no onSubmit, no "use client", and no name attributes on their inputs. Clicking submit triggers a native browser form submission — the page reloads and everything a visitor typed is silently discarded, with no error and no confirmation. These are the exact three moments this product exists to capture, and right now none of them work.

Once wired, a real submission genuinely can't reach the agent's Inbox — there's no shared store between the public site and the dashboard yet, the same disclosed architecture limit that applies everywhere else in this app. The honest ceiling here is a local "got it, Dave will follow up" confirmation, matching what ShowingRequestButton already achieves. Right now these three forms don't even reach that ceiling — they just silently fail.

Smaller finds in the same cluster: the AI chat bubble (present on every public page) has buttons that do nothing at all, not even a canned reply, despite already having local state wired up and an honest "Wireframe — not connected yet" caption printed right next to them. The homepage's Showcase section doesn't disclose that its listings come from a SimplyRETS trial-dataset agent ID standing in for Dave's real MLS ID, the way the equivalent code in /spotlight already does. And the About page overstates what /site/search actually shows ("straight from Dave's own MLS feed" — it's actually the whole board, other agents included, which is why every result already carries a "Listing courtesy of" line).

04 — Showcase / Spotlight

The one module backed by a real database — genuinely live, with a couple of real bugs.

Worth naming clearly: this is not a fixture. /spotlight reads and writes a real Postgres table (showcase_overrides, RLS enabled) via real server actions, merged with live SimplyRETS API calls. The bugs found here are real bugs in real, working infrastructure — not disclosed-absence gaps.

05 — CRM core

The most disciplined cluster in the app — small, concrete bugs, not gaps.

Inbox, Pipeline, and Calendar came back completely clean. Two real, narrow bugs found elsewhere in the cluster:

Smaller nit, same root cause in four places: the Contact "Source" dropdown's six option values are independently hand-typed in four different files with no shared fixture array backing them — a maintainability risk, not a functional break.

06 — Documents & the Marketing engine

Consistently the most rigorously self-disclosing area of the app.

Documents and Listing Graphics came back completely clean. Listing Alerts is the most transparent page in the entire app about what's missing — its own hero copy says "Nothing here sends an email today," on-screen, not just in a code comment. The real gaps found are narrow:

07 — Insight

Analytics is clean. Tracking Links' create flow is pure decoration.

08 — What's next

A prioritized list, not a wall of code — each row is already scoped and ready to build.

PriorityWhereWhat
1Public siteWire the 3 dead lead-capture forms (valuation, contact ×2) — the product's actual entry points don't work today.
2SpotlightDedupe synced/added listings by ID; fix the missing revalidatePath on Remove.
3InsightWire Tracking Links' create form to real state; fix the wrong "dana" domain literal.
4TasksStop the sort-sentinel date from leaking into the display for undated completed items.
5Contacts listReplace the fake "Send e-sign" log entry with a real deep-link into the Documents wizard.
6MarketingAdd a real delete-campaign action; force the first drip step's delay to zero.
7Site & Listing pagesFix the two disclosure/accuracy copy issues (demo agent ID, "own MLS feed" overstatement); wrap the listing-detail fetch in the same try/catch the home/search pages already use.

Client Portal's State C (multi-transaction switcher) isn't on this list — it needs a real product decision about extending Contact beyond 1:1 with Deal, not a fix, and that decision touches Pipeline too.