Skip to content
Liquidity

How we built it

One function prices the plan.

Liquidity is a Next.js app around a pure TypeScript engine. The demos call that engine. A model may explain the result or propose another look. It does not approve, and it does not invent a balance.

How a decision is made

The browser never prices a plan. Jeronimo, Ishayu's Capital Studio, and Your situation call optimizeFunding and render what comes back. They do not store a plan. Claude and CREAO are separate routes. They can explain or propose. They cannot approve, and they cannot invent a cent.

From a click to a plan
  1. Surfaces

    Web app and extension

    Jeronimo's /demo is a group dinner for about ten at BJ's Restaurant & Brewhouse. Ishayu's Capital Studio is /demo?studio=ishayu: $40,000 of international tuition, borrowing against an asset. Your situation is a sandbox a judge can edit. The extension pairs with a one-time code, then asks what a purchase would do.

  2. Server

    Next.js routes

    The browser calls same-origin handlers. It does not import the engine.

  3. Decision

    optimizeFunding

    Pure TypeScript. Integer cents. It does not read the clock, so the same inputs return the same plan.

  4. Record

    Convex

    Sessions, stored plans, the audit, and pairing hashes. The dinner story does not write them. Without a deployment URL, the same functions run in memory.

Called by routes, not by the engine

  • Claude

    Explains the stored plan. Cannot choose it.

  • CREAO

    Proposes a recovery. The engine recomputes it.

  • Alpaca

    Daily bars for volatility, and only when the gate is open.

Same inputs, same plan

  1. Inputs

    Accounts, tax lots, obligations, inflows, and policies, plus which bills to fund. Money is integer cents. Dates are YYYY-MM-DD, with no local-timezone shift.

  2. Candidates

    At most 25. Checking then savings, protected cash, savings then checking, specific-lot sales ordered by estimated tax, one approved existing line, and a few hybrids. That is the set we rank, not every possible plan.

  3. Constraints

    The protected lane skips inflows that are not verified. Hypothetical credit and property equity stay out. A sale that does not match a verified holding is refused before approval. The engine never calls a bank. Browser execute is rejected. Approval records a decision, and no money moves.

  4. Ranking

    Full coverage, then no policy violations, then lowest modeled cash cost in cents, then lower risk, then fewer actions, then a stable candidate id. Modeled cost includes illustrative federal tax on a simulated sale.

Where the demos call it

The dollar amounts on the demos are return values from this function. They are not typed into the screen.

  • POST /api/jeronimo/analyze

    Jeronimo's group dinner at BJ's Restaurant & Brewhouse. Read-only, on the server fixture.

  • POST /api/capital-studio

    Ishayu, at /demo?studio=ishayu. $40,000 of international tuition, borrowing against an asset. Returns the picture. It does not store a plan.

  • POST /api/custom/analyze

    Your situation, at /demo?studio=custom. A judge edits the books. The engine prices that picture and does not store a plan.

  • POST /api/purchase-impact

    The extension, after a pairing code. Read-only.

  • POST /api/plan

    Still runs the engine and storePlan for a session. /demo does not call it.

What we used

Five products show up in the code or in the design file the screens were built from. Each card is a call site.

Claude logo

POST /api/assistant

Claude

Why
Ask has to explain a plan the engine already chose. The model is not allowed to pick a different one.
Fit
The call is a single Messages request with no tools. A dollar figure that is not in the engine's fact list is thrown away, and the route quotes those facts instead.
Where
lib/agents/explainer posts to api.anthropic.com/v1/messages from POST /api/assistant, which explains a stored plan. The dinner story does not call it. With no API key, the answer is a fixture quotation, not a model run.
Tradeoff
OpenAI and Gemini can return constrained JSON too. We gave up tool use, so this call cannot approve, execute, or write a balance.
CREAO logo

POST /api/recovery

CREAO

Why
When a plan breaks, something has to propose a recovery without blocking the person who approves.
Fit
The hosted run is asynchronous. Its proposal is not stored as a new balance. The engine recomputes, and a candidate whose sale does not match a verified holding is left out.
Where
lib/providers/creao calls POST /runs and GET /runs/{id} on agent.creao.ai from POST and GET /api/recovery. The dinner story does not start a run. A missing key or agent id stays a fixture, not a finished run.
Tradeoff
A tool-calling loop on Claude or OpenAI could live in this process. We gave that up. A developer.creao.ai project key is rejected; the live path uses the app trigger.
Convex logo

Session store

Convex

Why
An anonymous session keeps its accounts, stored plan, audit chain, and extension pairing code on their own rows.
Fit
The Next handler runs the engine, then calls a mutation. Convex does not import the optimizer. getWorkspaceSnapshot is the session read. The dinner story does not subscribe to it.
Where
convex/schema.ts holds the rows. convex/extension.ts stores a SHA-256 of the pairing code, not the code. app/api/_lib/gateway.ts uses HTTP when a deployment URL is set, and the same functions in memory otherwise.
Tradeoff
Supabase would give Postgres, and Firebase a similar document model. We gave up SQL joins. No deployment URL means an in-memory gateway, not Convex cloud.
Alpaca logo

POST /api/liquidation

Alpaca

Why
A modeled sale can use historical daily bars for volatility. The sale price stays the scenario mark.
Fit
The client is read-only market data. It never calls a trading or brokerage-account endpoint. Live bars require the market-data flag and both keys. Otherwise the route keeps fixture history.
Where
POST /api/liquidation calls lib/providers/alpaca, which reads data.alpaca.markets only when the gate is open. The dinner story does not request bars.
Tradeoff
Polygon also sells daily bars, and adds quotes and trades. We gave those up. The default build sends no Alpaca request.
Figma logo

Design file

Figma

Why
The landing page was drawn as frames before the components that implement it.
Fit
Figma is the shared picture of those screens. It is not a runtime API, and this page has no frame. The app does not fetch the file.
Where
The file is xGGE4pCIWR49jnvTwEe6tr. Landing frames are mapped in components/landing/README.md. This page has no frame.
Tradeoff
Sketch, or laying the pages out only in code, would skip a shared frame file. We gave up a design tool the running app can query.