← Back to work
CASE STUDY · ECI · PORTFOLIO & TRADING

Portfolio and Investment Management Reimagined

I led the redesign of Savvy Wealth's portfolio and investment experience so an advisor can see and act on a household's holdings, trades, and money movement in one place, on live data, without leaving the platform.

WHAT IT DID
One Portfolio page replaced a fragmented three-page experience, live for every household that moved to Savvy's custodial platform through Fidelity NFS. Advisors can trade, move money, and enroll accounts in Savvy's managed models from the page itself, as they would at any competitive custodian, without a separate login.
MY ROLE
Design lead for the end-to-end advisor experience of Savvy's enhanced custodial integration (ECI). I worked directly with the founder and leadership team in weekly decision reviews to shape the final experience and get it approved. I also scoped in a second company OKR, SWIM enrollment (Savvy's own models, actively managed by our investment operations team), so the same page improved the core experience for every advisor while driving enrollment. I built the prototype in our own Vercel sandbox using the Savvy Kit design system.
TOOLS
Claude Code, Savvy Kit (design system), Figma, Linear, Notion
GOAL
Tighten up every loose end an advisor used to handle at the custodian, so that nothing they need to do for a client's investments depends on a custodian login
Context · Why this project existed

Savvy was becoming the brokerage, not just the software around one

For its first years Savvy was a workflow layer wrapped around someone else's brokerage. Advisors could see a household's investments as a two-day-old Orion* snapshot. The moment they needed to trade or move money, they left for Wealthscape or Schwab. ECI, Enhanced Custodian Integration, changed that: Savvy became a FINRA-registered introducing broker-dealer clearing through Fidelity NFS, with Fidelity's APIs integrated directly into the platform. The business case was margin and vertical integration, owning the economics and the experience instead of renting both.

That made the portfolio a design problem. A read-only page fed by a stale snapshot was fine as a tab between custodian sessions. It was not fine as the only place an advisor could look. If advisors were going to stop logging into custodians, every loose end they had been tying off there needed a real home in Savvy.

* Orion is a third-party service that copies account data out of the custodians once a day and hands Savvy a report, so what advisors saw was yesterday's snapshot rather than the live account.

Before ECI
Advisor + Client login 1 login 2 Savvy CRM · planning · read-only portfolio Wealthscape / Schwab Advisor Center trades · cashiering · forms act Custodian Fidelity IWS / Schwab custody · execution Orion holdings · performance snapshot copy ~2 days late

Two logins, two tabs. Everything that touches money happens on the right. Savvy only ever sees a stale copy of it.

After ECI
Advisor + Client one login no access Savvy view · trade · move money · service accounts Wealthscape ops backstop only live API data up · actions down ops only Fidelity NFS clearing · custody Savvy as the FINRA-registered introducing broker-dealer

One login. Live data flows up, actions flow down. Advisors and clients never see Wealthscape.

Before ECI, the money lived at the custodian. Account data took a day to reach Orion and another day to reach Savvy, so advisors worked from a two-day-old snapshot. With ECI, Savvy is the only surface an advisor or client needs to touch. Live data flows up and actions flow down through Fidelity's APIs, which Savvy can access directly as the broker-dealer.

Before and after ECI

The honest picture was that Savvy didn't own the surfaces where the work happened. All we had on the investment side was delayed holdings and performance data fed through an Orion integration — a snapshot, roughly two days stale. We lacked automation and immediate execution of money movement tasks and clearing trades. For anything that touched the money itself, advisors had a habit of logging directly into the custodian to avoid any delays. That is what turned ECI from a back-end initiative into a design problem. If advisors were going to stop relying on Wealthscape and Schwab logins, every loose end they had been quietly tying off on a custodian site — checking a live balance, placing a trade, moving cash, confirming which accounts were on a managed model — needed a real home in Savvy. A read-only portfolio page fed by a two-day-old snapshot was fine as a tab between custodian sessions. It was not fine as the only place an advisor could look.

TaskBefore ECIAfter ECI
Account openingEverything was manual. Savvy captured intake, then the CSA team submitted client-e-signed forms to Fidelity through Wealthscape, waited days on opaque timelines, and relayed progress to advisors by handIn-product bulk data ingestion, API-driven submission, and error handling and tracking. Opening is automatic and transparent, and cuts manual ops overhead
Transfer of assetsAll money-in flows lived at the custodianTOA APIs in Savvy — Determine Transferability, Custodian Lookup, Asset Transfer Processing
This case studyTradingAdvisors traded in Schwab or WealthscapeSavvy trading UI on Fidelity's Order Entry API
This case studyMoney movementAll at the custodianFull Money Movement API surface in Savvy, with firm-audience parity for client-initiated requests
This case studyHoldings and performanceOrion transmission data, roughly two days lateLive API pulls for balances and positions
This case studyStatements and tax docsCustodian-branded, custodian-deliveredDocument APIs render them inside Savvy

Six of ECI's twelve brokerage primitives. The four tagged ones become visible on this page; account opening and transfer of assets live in the separate Fidelity NFS advisor transfer flow. Compliance and supervision moved too: BD supervision under a named principal and trade review queues shaped what an advisor can do directly versus through review.

"If a routine task sends an advisor or client into Wealthscape, that surface has failed and is on the roadmap."

— ECI north-star test, internal product vision
The problem that research validated

Three pages, actions that wait on ops, and the details that matter buried too deep

An advisor's view of a household was spread across Net worth, Managed investments, and Strategy, each with its own layout and its own definition of an account. Trades and money movement existed only as tasks to the ops team, who executed them by hand at the custodian. Most advisors made the same calculation: skip the task, log into the custodian, do it yourself.

To ground that picture, I ran five interviews with advisors walking through the current portfolio on their own households, looking for the gaps between what the page showed and what they actually needed to do. The four costs below, and the quotes under each, came out of those sessions.

The Managed investments page as it stood — a walk through the Allison & Frank Chan household. Note the "Refresh data" button and "Last updated" stamp under the value: the page knows its own data is stale.

COST 1

No single source of truth

Three pages, three layouts. An advisor prepping for a client meeting stitches the picture together in their head.

“Before a review I have Net worth open in one tab and Managed investments in another, and I'm adding them up on a notepad.”

Advisor, 1+ year on platform, $220M AUM
COST 2

Deep on data, empty on action

Tax lots, cost basis, a full ledger. None of it connects to a trade or a transfer.

“To be honest, I didn't even know the dashboard showed lots. There's so many clicks, I'm confident I don't know everything you guys offer. If you do show lots, I need to be able to trade them. Just showing me lots isn't even helpful.”

Advisor, 1+ year on platform, $132M AUM
COST 3

No proactive value

Unmanaged, cash-heavy, or concentrated money just sits there. Nothing points at the opportunity to move it onto a Savvy model.

“Nothing tells me a client has been sitting in cash for six months. It can cost me a client if they find out that I haven't managed idle cash. This is where I see the value of enrolling in SWIM models but I don't know how to get started. I need to see a proposal to present to my client.”

Advisor, 3 months on platform, $120M AUM
COST 4

Stale by design

Every number is an Orion snapshot. Advisors learned not to trust the page for anything that touched money.

“If it says 'last updated two days ago,' I don't quote it to a client. I open the custodian.”

Advisor group, 1+ year on platform, $1.6B AUM

Same household, two pages that don't know about each other

Net worth and Managed investments are separate destinations under the same Portfolio tab. Both totals are useful — everything the household holds, and the slice Savvy manages — but they sit on different pages with different layouts, and nothing connects them. To see how the managed accounts roll up into the household, an advisor has to hold both pages in their head. Neither page has a way to act on any of the accounts it shows.

Net worthPortfolio · page 1
The old Net worth page for the Chan household, showing a $12.5M net worth chart and a list of Savvy investments accounts identified by masked account number
Managed investmentsPortfolio · page 2
The old Managed investments page for the same household, showing a $9.5M value, a 'Refresh data' button and a 'Last updated' date

The same household, split across two pages. Net worth lists accounts by a masked number and custodian; Managed investments doesn't list accounts at all until you dig into a sub-tab. The redesign keeps both totals — it puts them on one page.

Deep on data, empty on action

Drill in and the detail is real: asset classes, positions, tax lots with cost basis and gain/loss type, a full transaction ledger. But none of it connects to an action. Trades and money movement did exist in Savvy, as tasks — but a task went to the ops team, who executed it by hand at the custodian, so every request carried a delay. Most advisors made the same calculation: skip the task, log into the custodian, and do it themselves. And nothing on the page ever suggested a model recommendation at all.

Holdings detailtax lots, no actions
A holdings detail modal for DFA US Core Equity II, showing account weight, quantity, cost basis and two tax lots, with no action buttons
Transactionsaccounts named by number
The Transactions sub-tab, where every row identifies its account as 'Allison Chan – Trust – Charles Schwab – 2985'

The holdings modal has everything an advisor would want to know before acting, and no way to act from it. In Transactions, the only handle on an account is a custodian name and the last four digits.

Problem statement

How might we redesign the household portfolio experience to reach parity with custodial platforms, replace the dated structures advisors have learned to dread with something modern and easy to use, proactively recommend Savvy managed models an advisor can act on, and raise the integrity of every account's data?

Scoping · Two OKRs, one page

Pulling a competing OKR into scope

The brief was an ECI project: get the portfolio ready for accounts held at Savvy through Fidelity NFS. The company had a second OKR the same page could move, SWIM enrollment, tracked by a different team with no design attached. I scoped it in.

SWIM, Savvy Wealth Investment Management, is the in-house program where an advisor enrolls a client account into a managed strategy for a fee. It is the primary revenue lever for the investment business. ECI moves assets onto Savvy's custody; SWIM monetizes them once they're there. Both OKRs reduce to the same question an advisor asks while looking at a household: what should I do with this account? The portfolio page is the only place both answers can live. The case for pulling it in was sitting in the old product: unmanaged accounts sat in plain sight with nothing pointing at them.

Bet 1 · The accounts list

One accounts list that serves both OKRs without sacrificing either

I made the first bet on the list itself, and I started with a model. I reduced the two OKRs to two questions about every account: is Savvy the custodian, and is it on a managed model? Put them on a grid and each account's position tells you what data it can show, how its trades execute, and whether there is anything to recommend.

SWIM · ON A MANAGED MODEL? Yes No ECI · SAVVY IS CUSTODIAN? Yes No Live & managed ECI · CUSTODY Live data · trades are managed by Savvy SWIM · MODEL On a model · monitor, rebalance WHERE THE VALUE IS Live, unmanaged ECI · CUSTODY Live data · advisor trades directly SWIM · MODEL No model · recommend one, in the row Managed, delayed ECI · CUSTODY Delayed data · trades are managed by Savvy SWIM · MODEL On a model · monitor Delayed, unmanaged ECI · CUSTODY Delayed data · advisor trades via task SWIM · MODEL No model · recommend one, via task

Custody sets the data and how edits reach the custodian. Model status sets who trades: the advisor on unmanaged accounts, Savvy's investment team on managed ones. Top right is the cell that makes money: live accounts with no model yet.

New Accounts list view that supports every quadrant of the matrix

This is why I decided to group accounts by custody rather than by account type or strategy. A household mid-transition has some accounts on Fidelity NFS and some still at Schwab, and most households will live in that state for a while. Held at Savvy shows live data and day change on every row. Held elsewhere shows delayed data and says so. The model also had to handle sleeves, where one account splits into a managed core and a self-directed remainder, and scope, where the whole page rolls up to any subset of accounts under the same rules. Accounts not yet on ECI get a direct pathway to upgrade: every Held elsewhere row says "Upgrade custodian for live data" and the group ends in an Upgrade custodian button. I insisted that nudge sit alongside the SWIM one rather than replace it, so an unmanaged account held elsewhere still shows "Not enrolled in SWIM" and a request-a-review link. The page can move an account up the matrix and across it at the same time.

Accounts listGrouped by custody, with the gap visible in the row
Managed accounts list for the Chan household. Held at Savvy shows a Roth IRA on Savvy Strategic 80/20 and Allison's Brokerage marked Not enrolled in SWIM with a Request a portfolio review link. Held elsewhere shows a Schwab joint brokerage and a sleeved Chan Family Trust with an Upgrade custodian for live data note.
Bet 2 · Doubling down on SWIM enrollment

An unmanaged account is a recommendation waiting to happen

Bet 1 made the gap visible in the main accounts row, front and center on the portfolio page. Bet 2 turns that gap into a path. The old product offered a marketing paragraph and a generic button. The new one names a specific model and the reason for it, in the row the advisor is already reading, and gets from there to enrollment in four clicks without leaving the page.

The old enrollment paths

Accounts tabEnrollment as a table cell
The old Accounts tab, where an unmanaged sleeve shows a plain 'Enroll a strategy' button in the Strategy column, visually identical to the strategy-name buttons around it
Strategy tabOne generic CTA
The old Strategy tab: a paragraph describing SWIM, a single 'Enroll in Savvy Wealth Investment Management' button, and two resource links

On the left, "Enroll a strategy" is styled like every other strategy name in the column. On the right, a marketing paragraph and one button — no account, no reason, no recommended model. This is the entry point to Savvy's biggest revenue driver.

The new enrollment path: four clicks from the row

The recommendation itself comes from Savvy Intelligence, our AI layer. To bring it to life I worked with the AI team and the internal investments team to define the mappings: logic that reads an account's holdings, cash position, and concentration and matches it to the closest Savvy SWIM model. The investments team owns which model a given profile should map to; the AI team owns how the match is made; the design owns how the answer shows up in the row, with the model named and the reason stated so an advisor can trust it before they act on it.

01 · Nudge
Managed accounts list where Allison's Brokerage shows a Not enrolled in SWIM chip and a Get SWIM recommendation link

A "Not enrolled" chip and a recommendation link on the row, next to accounts that show their strategy.

02 · Reason
Account overview with a Models widget recommending Savvy Strategic 60/40, an explanation, allocation comparison bars, management fee, an Enroll in SWIM button and a View Proposal Report link

A named model, Savvy Strategic 60/40, and why: 63% cash and a concentrated NVDA position.

03 · Proposal
Investment proposal report modal comparing the client portfolio to the recommended Savvy Strategic 60/40 model, with Download PDF and Enroll in this model buttons

A client-ready proposal generated from the row, downloadable for the meeting.

04 · Enroll
Enroll in SWIM sheet with the account, Savvy Strategic Models strategy and 60/40 allocation preselected

Account, strategy and allocation already filled in. Two steps, then it routes to Savvy Investment Services.

Bet 3 · The action

Every action lives where an advisor's mental model expects it, next to the account or position it applies to, and forks by custody without the advisor having to know which rule applies

A Trade button sits on every position. Transfer money sits in the header of every view. I designed one button that forks: for an account held at Savvy it executes directly through Fidelity's APIs, for an account held elsewhere it opens an Ops task instead. The advisor never has to hold that rule in their head, because the button already does.

Trade and transfer, right where you need them

Positions consolidate across every account and expand to per-account lots, and a Trade button sits on every row. Transfer money sits in the header of every view and on every account, a docked three-step sheet for ACH, wire, check, or internal, with an optional trade step before review. The entry point is wherever the advisor is already looking, so the action never requires a trip to a different page, let alone a different platform.

Positions table grouped by asset category, with VTI and VOO expanded to show per-account lots and a Trade button on each row

Positions grouped by asset category, expanded to per-account lots, with Trade on every row and Place trade and Transfer money in the header above.

Live market data, one click from the position

Click any position and it opens with a live quote: price, day change, previous close, open, today's range, the 52-week range, and a chart, with Buy and Sell one tap away. I pushed for the live quote to open from the position itself, because it closed another reason advisors kept a second tab open.

I always have Yahoo Finance open so I can see real-time market data on a ticker. There's so much the dashboard doesn't show that I feel more comfortable going directly into the custodian or using a public source for live market info.

Advisor, research interview
VOO position drill-in with live price, Buy and Sell buttons, previous close, open, today's range, 52-week range and a one-month chart

A position opened from the table: live price and day change, the ranges an advisor used to look up elsewhere, and the trade actions on the same card.

Beneficiaries, and the same button doing two different things

Beneficiaries are the clearest example of the fork. On an account held at Savvy, Edit opens a modal and the change is made in place: name, allocation, primary or contingent, saved straight through Fidelity's APIs. On an account held elsewhere, the same Edit button opens an Ops task instead, because the custodian still owns the record. The advisor clicks the same control in the same place either way and never has to know which path they're on.

Editing beneficiaries on two accounts in the same household. The account held at Savvy opens an edit modal and saves immediately; the account held elsewhere routes the same request to an Ops task.

Also shipped

The rest of the page, rebuilt on live data

The three bets carried the argument. I rebuilt the rest of the page around them, working view by view against the list of things advisors used to look up at the custodian, until nothing was missing.

Customizable right rail

Allocation widget with asset categories, values and change, and a Show target toggle
Daily top movers across household widget
Documents and statements widget with 2025 tax documents and statements

A customizable right rail: allocation, live top movers, in-app tax docs and statements.

Benchmarked performance

Total performance chart with an S&P 500 benchmark overlaid and a stat row

Benchmarked performance with intraday ranges only live accounts can offer.

Net worth and linked accounts

Net worth view with a total balance, net worth trend chart, assets vs liabilities chart, and totals for assets, liabilities, net worth and investable assets
Investments list under Net worth showing NFS accounts marked Live, Schwab accounts synced today, and a Robinhood account flagged Disconnected and dated to its last sync

Net worth as its own view: assets split from liabilities, the trend charted, and investable assets broken out. Every linked account shows whether it's still connected. The Robinhood account is flagged Disconnected and dated to its last sync, so a three-week-old balance is never read as today's.

Method · Designed in the codebase

A prototype execs could click through, built in the production design system

I built the prototype in Savvy Kit, the production design system, so it read as a real cut of the product rather than a mockup. A scenario switcher seeded one Chan account in each quadrant, so every path in the model was demonstrable rather than hypothetical. Order execution, aggregation and ops routing were simulated and labelled as such, so no one mistook scaffolding for a requirement.

Building in the real system also exposed its gaps. With direct access to production, I worked with our design engineer to agree on the fix and shipped new component variants, like a compact StatBlock, straight into our Storybook rather than leaving forks in the prototype.

The redesigned Portfolio landing page for the Chan household: secondary nav, Place trade and Transfer money buttons, a delayed-data ribbon, a concentration-risk alert, total performance chart, and a right rail

The prototype as reviewed. Place trade and Transfer money in the header on every view, a delayed-data ribbon for households with accounts held elsewhere, and a risk-alert deck before the advisor scrolls.

Iteration · What changed under review

What the exec review changed, and where I held my ground

What the exec review changed

The design went through weekly decision reviews with the founder and leadership team, and the biggest debate was about accounts that hadn't moved to ECI yet. The business wanted those households repapered quickly, so the review pushed for the page to make the upgrade case as hard as possible. Out of those sessions I gave the upgrade nudge a real home: an "Upgrade custodian for live data" note on every held-elsewhere row and a button at the end of the group.

What I pushed back on

The one thing I held my ground on was volume. The ask was for the upgrade prompt to be loud: banners, badges, a promo wherever a held-elsewhere account appeared. I pushed back. Our highest-value advisors and advisor groups hold the most accounts still at other custodians, and they would be the ones seeing that promo on every row of every household, every day. That exhausts the people we most need to keep.

Instead I made the difference felt rather than announced. A quiet "Delayed data" banner and subtle warning marks sit exactly where a number may be stale, so the cost of staying put is visible in the data itself. And ECI and non-ECI accounts got genuinely different experiences for the same task, like editing beneficiaries: in place for an account held at Savvy, an Ops task for one held elsewhere. The bet was that advisors would want to upgrade from their own first-hand experience of the gap, not because we shouted at them to.

The same Edit beneficiaries control on two accounts in one household. Held at Savvy opens a modal and saves immediately; held elsewhere routes to an Ops task. The upgrade case is made by the experience, not a banner.

Outcome

Shipped in July, and the advisors followed

A walk through the shipped experience — the Chan household from landing page to account detail, on live data.

May 2026

ECI launched

Savvy goes live as an introducing broker-dealer clearing through Fidelity NFS. First accounts open on the new custody.

July 2026

Portfolio redesign launched

The single Portfolio page replaces Net worth, Managed investments, and Strategy for every household on the platform.

Net new advisors who joined Savvy Wealth because of this initiative, within one quarter 4
Assets transferred into ECI custody in that quarter ~$200MAUM