ISM.Isaac Sven Manzanarez, product designer
Product Designer  ·  Portfolio 2026

judgement

product / shipped code

outcome

evidence / consequenceback to judgement

I design products, build them in code, and answer for whether they work.

Most designers hand off before the loop closes, so the outcome never reaches them. I own the whole arc, which means the result corrects the next decision.

DESIGNS  Figma · systems
BUILDS  Next.js · Supabase
SHIPS  real outcomes
IdentityProduct Designer
DisciplineDesign + Build
StatusConnecticut · NYC metro
AuthTN-eligible (CA)
Approach

Light finds its color at the edges. I find demand at the periphery.

Don't fight for the crowded center of a market — read for the segment nobody is serving, then design and ship the product, brand, and infrastructure to capture it. Design taste and engineering rigor aren't two conversations for me; they're one motion. That's how a single hire ends up owning the whole arc.

The Method — Demand Engineering
01 / LOCATE

Locate

Read for the demand nobody is capturing yet — the underserved edge.

02 / TRANSLATE

Translate

Turn the gap into product, brand, and message the market acts on.

03 / STAGE

Stage

Ship it where the market can find it and say yes with one tap.

04 / COMPOUND

Compound

Each win de-risks the next — proof stacks into momentum.

Selected work

03 — each proves a piece of the claim
PLATE 01Designed & Built · end to end

Western Casa — a platform for hard-to-move luxury listings, designed and shipped in code

High-end listings sit on the market because agents can't tell which enquiries are real. Western Casa is a production, multi-tenant SaaS that gives each agent a branded listing page with an embedded Buyer Match Quiz, scoring how ready and how appropriate a buyer is before the lead reaches them, then firing a one-tap WhatsApp opener.

I owned all of it: product design, information architecture, and the front-end build. The computeMatchScore engine, a versioned scoring rubric, a multi-tenant Postgres model with row-level security, and Mexico's LFPDPPP privacy law implemented end to end.

Role
Design + full-stack build
Stack
Next.js 14 · TypeScript · Supabase (Postgres/RLS) · Tailwind · Vercel
Outcome
Agent response ~30 min → under 5 sec
Status
Live · launched with a paying client, $4.6M listing
Visit the live platform ↗
PLATE 01 — WESTERN.CASA4:3
The live Casa Rosa Morada listing page, showing the property name, description and the single call to action that opens the Buyer Match Quiz.
Problem

Luxury agents lose deals to slow response. The industry norm is 20–45 minutes to a new lead, and published research (MIT Sloan, HBR) ties response time directly to conversion — while agents burn hours on buyers who were never going to close.

Approach

A per-listing branded page with an embedded Buyer Match Quiz that scores intent before the lead reaches the agent, then fires a one-tap WhatsApp opener. Response compresses to under 5 seconds, and only qualified buyers get through.

What I designed & built

computeMatchScore() — a pure, auditable function turning buyer inputs (budget, timeline, financing, origin) into a 0–100 score, a tier, and a transparent breakdown. A versioned per-listing rubric, never mutated in place. A multi-tenant Postgres model with row-level security and full attribution. Shipped in six phases (and squashed a Vercel serverless dangling-promise bug along the way).

Compliance & outcome

Mexico's LFPDPPP end to end — versioned privacy notice, consent timestamping, automated ARCO rights on a 20-day SLA. Live with first client Kari Estrada (Century 21 Heavenly), a $4.64M MXN listing. Response time: ~30 min → under 5 sec.

WESTERN.CASA Listing page Casa Rosa Morada · live FIG A

The page a buyer actually lands on

The listing sells the house. The one button is what turns a visitor into a scored lead.

Everything above the fold is doing conventional listing work. The single call to action is the entry to the Buyer Match Quiz, and it is the only path into the funnel, which is why nothing else on the page competes with it.

rosa-morada.western.casa
The live Casa Rosa Morada listing page: agent branding and WhatsApp contact in the header, a full-bleed property photograph, the property name and description, a single call to action reading "¿Es ésta casa para usted?", and a strip of listing attributes along the bottom.
  1. 1 Quiz entryThe only route into the Buyer Match Quiz. Every scored lead in the funnel starts at this button.
  2. 2 Per-tenant branding and contactAgent identity, phone and WhatsApp are configuration, not code. One codebase serves every agent.
  3. 3 Structured listing attributesBedrooms, baths, built area, lot and price are the property side of the comparison computeMatchScore runs a buyer against.
Role
Design and build. Page, brand system, CTA hierarchy, tenant config.
Locale
Spanish-first · MXN pricing · metric area
The live Casa Rosa Morada listing page. The page does ordinary listing work above the fold and then narrows to a single call to action, because the platform only earns its value once a visitor enters the Buyer Match Quiz and becomes a scored lead.
— WESTERN.CASA · SYSTEM DIAGRAM
Platform Architecture — Multi-Tenant
TENANCY · row-level security
SCALE · N agents × N listings
DEPLOY · single Vercel project
01
Presentation
— Tenant A
agent_slug = 'kari-estrada'
Listing Page
app/[listing]/page.tsx
Buyer Match Quiz
components/BuyerMatchQuiz.tsx
rosa-morada.western.casa
— Tenant B
agent_slug = 'agent-2'
Listing Page
app/[listing]/page.tsx
Buyer Match Quiz
components/BuyerMatchQuiz.tsx
casa-luna.western.casa
02
API
Shared Application Runtime
— single codebase · every tenant
Route Handler
app/api/qualified-leads/route.ts
computeMatchScore Engine
lib/scoring/real-estate.ts
Notification Dispatch
lib/notifications/{buyer,agent}.ts
03
Data
— ROW-LEVEL SECURITY BOUNDARY
POLICY · WHERE agent_slug = auth.tenant()
Supabase · Postgres 15
MANAGED · US-EAST-1 · DAILY BACKUP
real_estate_leads
Every lead scoped by (agent_slug, listing_slug). Same table serves all tenants; RLS isolates rows.
agent_slug = 'kari-estrada'tenant A rows
agent_slug = 'agent-2'tenant B rows
scoring_rubrics
Versioned per listing. Locked to lead at capture.
V rosa-morada-v1 · casa-luna-v1 · …
attribution + consent
UTM source, referrer, LFPDPPP consent, aviso version.
AUDIT immutable · timestamped
WESTERN.CASA platform architecture. One codebase and one Postgres table serve every tenant; isolation is enforced at the database by a row-level security policy rather than in application code, so a routing bug cannot leak one agent’s leads to another.
— WESTERN.CASA · SYSTEM DIAGRAM
Scoring — Pipeline
FUNCTION · pure · deterministic
RUBRIC · rosa-morada-v1
RUNTIME · Node · edge-safe
— Data Flow · Left to Right
01 · Input
Quiz Inputs
budget · timeline · financing · origin
02 · Focus
computeMatchScore()
pure fn · rubric-weighted
03 · Output
{ score, tier, breakdown }
score 0–100 · tier gate
04 · Persist
Supabase
insert + attribute + audit
05 · Dispatch
WhatsApp + Email
tier-gated · Resend + wa.me
— Node 02 · Hero
computeMatchScore()
lib/scoring/real-estate.ts
inputs · BuyerQuizPayload
rubric · ListingRubric (versioned)
score · integer 0–100
tier · hot | warm | cold | disqualified
breakdown · per-factor point trace
PURE
DETERMINISTIC
NO I/O
FULLY UNIT-TESTABLE
RUBRIC-VERSIONED
lib/scoring/real-estate.ts
TypeScript
123456789101112131415161718
function computeMatchScore(inputs, rubric): {
  score: number,
  tier: 'hot' | 'warm' | 'cold' | 'disqualified',
  breakdown: Array<{ factor: string, points: number }>
} {
  const breakdown = [
    { factor: 'budget',    points: rubric.budget[inputs.budget]       ?? 0 }, // max 30
    { factor: 'timeline',  points: rubric.timeline[inputs.timeline]   ?? 0 }, // max 25
    { factor: 'financing', points: rubric.financing[inputs.financing] ?? 0 }, // max 20
    { factor: 'origin',    points: rubric.originCity(inputs.origin)       }, // max 10
  ];

  const score = breakdown.reduce((s, b) => s + b.points, 0);
  const tier  = score >= 75 ? 'hot'
              : score >= 55 ? 'warm'
              : score >= 30 ? 'cold' : 'disqualified';

  return { score, tier, breakdown };
}
The Buyer Match Quiz scoring pipeline. computeMatchScore is a pure, deterministic function with no I/O — it takes quiz inputs and a versioned rubric and returns a score, a tier, and a per-factor breakdown. That makes it fully unit-testable, and it locks the rubric version to each lead at capture so historical scores stay explainable.
WESTERN.CASA Demand funnel Rosa Morada · multi-tenant FIG D

Locate → Translate → Stage → Compound

The stage worth owning is the one where an enquiry becomes a lead worth calling.

Reach is easy to buy and closing belongs to the agent. The stage in between is the one nobody owns, so that is the one the platform runs: turning an anonymous enquiry into a scored, routed lead an agent can act on.

  1. 01 · REACHPaid + organic impressions

    184,000

  2. 02 · SESSIONLanding page session

    8,420−95.4%

  3. 03 · INTENTEnquiry submitted

    612−92.7%

  4. 04 · OWNED STAGEScored, deduped, routed

    487−20.4%

  5. 05 · CONTACTAgent first response

    368−24.4%

  6. 06 · OUTCOMEShowing booked

    114−69.0%

Role
Design and build. Funnel model, schema, UI, routing logic, tenant configuration.
Stack
Next.js 14 · TypeScript · Supabase
Row-level tenancy · LFPDPPP-compliant
Outcome
Live with a paying client.
rosa-morada.western.casa
Western Casa demand funnel. The platform works at one stage, scoring and routing enquiries, because that is the step the media side and the sales side both leave alone. Stage volumes are illustrative pending final client reporting.
PLATE 02Architected · cross-surface product

Pawmates — architecting the retention core as a founding member

Founding member of a hyperlocal social app for pet owners. I architected Neighbourhoods — the core retention feature — as a cross-surface system spanning six product surfaces around a single shared state key (homeHoodId).

I reframed the company's central problem from downloads to neighbourhood density (10 / 25 / 100 verified-duo thresholds, now the north-star metric), and locked the hard product decisions in an interactive prototype before engineering ever touched them.

Role
Founding member · product design
Scope
6 product surfaces, one shared state key
Craft
25+ prototype iterations · ~80 wired flows
Shift
Downloads → density as the north-star metric
PLATE 02 — PAWMATES4:3

Pawmates · Neighbourhoods30 specified screens

Pawmates Neighbourhoods, For You screen.For YouGlobal feed
Pawmates Neighbourhoods, Hood feed screen.Hood feedScoped to your hood
Pawmates Neighbourhoods, Hood map screen.Hood mapBoundary drawn

One field · three surfaceshomeHoodId

Problem

A large but geographically dispersed user base with roughly 1% activation. Density — not downloads — is the product: below a threshold, the neighbourhood reciprocity loop never spins up.

Approach

I reframed the north-star from downloads to neighbourhood density (10 / 25 / 100 verified-duo thresholds) and architected Neighbourhoods as a cross-surface system around one shared state key, homeHoodId.

What I did

25+ prototype iterations, ~80 wired flows. Locked three product decisions in prototype before spec — hood-first Meet above a density floor, Lost-Pet alerts opening direct chat with no match-gate, and home-hood selection at onboarding. Designed a two-loop retention architecture (in-app density loop + IRL dog-park loop) and named push notifications as the load-bearing gap.

Outcome

The density framework became the company's north-star metric, converted into a sequenced nine-project roadmap, with the founder-blocking decisions resolved before engineering handoff.

PAWMATES Neighbourhoods Cross-surface map FIG A

The null column is the product work

One optional field drives six surfaces, so the real work was deciding what each does when it’s empty.

Setting a home neighbourhood is optional at signup, so every surface that keys off it needs a decided answer for the empty case. Those decisions are the actual product work, not the field itself.

Single field homeHoodId users.home_hood_id uuid · nullable · set at onboarding step 3
Behaviour of each surface when homeHoodId is set versus null
Surface Behaviour — homeHoodId set Fallback — homeHoodId null
Feed Hood tab is the default; the feed shows posts from your home hood. No Hood tab. Global “For You” only, with a persistent set-your-hood prompt.
Map Opens centred on your hood with its boundary drawn; pins scoped to it. Centres on device GPS. No boundary — city-wide pins.
Lost Pets Alerts scoped to your hood; posting defaults to it. Posting still works (last-seen 1 km radius). No hood alert feed to subscribe to.
Notifications Hood activity — new neighbours, meetups, alerts — drives push. No hood push: the re-engagement channel goes dark. Account and DMs only.
Ad Targeting Placed in the hood’s targetable inventory for local advertisers. Not locally targetable. Falls back to city-level or house ads.
Search Results boosted and ranked by home-hood proximity. Global results, no local ranking boost.

The null column is the figure. Each fallback is a decision, not a default — every surface degrades to something intentional, never to a broken state.

Role
Product definition and spec for the field the whole app keys off.
Surfaces touched
6
Constraint
Optional at signup, so every surface must degrade gracefully.
Pawmates Neighbourhoods. A single nullable field, homeHoodId, set once during onboarding, changes how six product surfaces behave. Because it is optional, each surface needed a designed fallback rather than an error state.
PAWMATES Onboarding v0.2 Before / after FIG B

Fewer steps, later ask

Activation improved by removing steps and asking later, not by adding persuasion.

Four low-value steps came out and the notification permission moved to after the user has seen the feed, so the prompt arrives once there is something to be notified about.

4 steps removed·1 permission deferred · nothing added

BEFOREv0.0 · 10 steps

  1. Welcome carousel (3 screens)4%
  2. Create account11%
  3. Verify phone number9%
  4. Allow notificationsSystem prompt — asked early24%
  5. Add your pet’s photo7%
  6. Add breed & age6%
  7. Write a pet bio5%
  8. Set home neighbourhood8%
  9. Follow 5 suggested duos9%
  10. Tutorial overlay5%

AFTERv0.2 · 6 steps

  1. Welcome (1 screen)3%
  2. Create account10%
  3. Verify phone number8%
  4. Add your pet’s photo6%
  5. Set home neighbourhood7%
  6. Allow notificationsMoved from step 04 — after first feed view9%

Tracked user actions+30%

Role
First-run flow — install to first real action.
Method
Removed four low-value steps; deferred the permission ask.
Result
More new users reach their first action.
Pawmates onboarding, v0.0 to v0.2. The notification permission moved from step four to step six, after the user has seen the feed, and four steps that gathered optional profile detail were cut entirely. Per-step drop-off figures are illustrative.
PAWMATES Retention Two-loop architecture FIG C

Two loops, one shared step

Two loops that would run separately, except both pass through post.

A content loop and a local loop, each one self-sustaining. Both pass through the same step, so activity in either feeds the other, and a user who arrives through the neighbourhood ends up inside the content loop without being asked to.

CONTENT LOOP LOCAL LOOP post shares to the feed engagement likes · comments · saves notification reaction → push return opens the app again neighbourhood home-hood feed discovery nearby duos & places connection follow · message
Content loop
  1. engagementlikes · comments · saves
  2. notificationreaction → push
  3. returnopens the app again

→ returns to step 01 (post)

Local loop
  1. neighbourhoodhome-hood feed
  2. discoverynearby duos & places
  3. connectionfollow · message

→ returns to step 01 (neighbourhood)

Content loop
Trigger: a post is published.
Signal: notification open-rate → return sessions
Local loop
Trigger: a home hood is set.
Signal: new connections per active duo
Role
The two cycles that bring users back, and where they interlock.
Loops
2 · content, local
Shared node
post
Pawmates retention architecture. Two independent loops, one driven by content and notifications and one by neighbourhood discovery, both pass through the same step of publishing a post. That shared step is what couples them instead of leaving two separate products.
PLATE 03Systematized · design-to-code

Pawmates — a design system engineering builds from

I built and documented the full design system: design tokens (tokens.js), a typography scale, a UI component library, and the DuoAvatar pattern that treats the pet-owner pair as one identity unit.

Then I audited the shipped app against its own documentation, caught the drift (a stale purple against the live #7828F0), and set the corrected values as the single source of truth — the kind of design-to-code reconciliation that keeps a team on-model without asking.

Role
Design systems
Deliverable
tokens.js · component library · living guide
Method
Design-to-code, shipped-app drift audit
PLATE 03 — DESIGN SYSTEM3:4

Pawmates · tokensas-built v0.8

Display Heading Title Body copy for reading
PrimarySecondary GhostDestructive

Type · colour · spacingT.purple #7828F0

Problem

The design documentation had drifted from the shipped app — including a stale brand purple — with no single source of truth for engineering to build from.

Approach

Reverse-engineered the live app and reconciled three prior draft systems into one canonical reference — visual and verbal.

What I built

Design tokens (tokens.js), a compressed typography scale, a UI component library, and the DuoAvatar pattern that treats the pet-owner pair as one identity. Codified non-negotiable brand rules — pet purple, owner orange; one gradient; lost-red reserved for alerts.

Outcome

Audited shipped against documented, corrected the drift (#6B3FA0 → the live #7828F0), and delivered an interactive brand guideline as the single source of truth the team builds from.

DESIGN SYSTEM Token → Code → Surface Refraction FIG A

One definition, three surfaces

Components reference a token instead of storing a colour, so one change moves everything.

The design file and the codebase read from the same source. A designer changes a variable, the build resolves it, and every surface moves. This figure is rendered in the system it documents.

  1. 01 · Design Figma variable
    accent/signal#F7A23A
    COLLECTION
    refraction
    MODE
    dark
    SCOPE
    fill · stroke · text
    EDITED BY
    design
  2. export 02 · Source of truth Token layer

    tokens/refraction.css

    /* generated — do not edit */
    --accent-signal: #F7A23A;
    --accent-flow  : #5AA2FF;

    tokens/index.ts

    export const accent = {
      signal: 'var(--accent-signal)',
      flow  : 'var(--accent-flow)',
    } as const;
  3. build 03 · Product Rendered surface

    LEAD DETAIL — PRIORITY

    Scored 92 · route now

    Source: paid social

    SLA 04:12 remaining

    ASSIGN AGENT

    CONSUMED BY
    Button · Badge · Chart · Alert · Focus ring

Source
Figma variables. Designers edit the collection, never the component.
Pipeline
Variable export → CSS custom properties → typed TS tokens → build.
Guarantee
One edit, every surface.
Hardcoded values fail the lint rule.
How a single design token travels from a Figma variable, through a generated token layer that acts as the only source of truth, to the rendered product surface. A colour change becomes one edit rather than a search-and-replace across components.
DESIGN SYSTEM Components Button FIG B

Small API, large visual surface

Three props and two CSS states cover twenty rendered cells.

Every cell below is a live element rather than a screenshot, the same component rendered under each combination. The system is what keeps that surface manageable instead of twenty hand-built buttons.

Rendered in the as-built Pawmates tokens — T.purple, T.redScroll horizontally →

Button component rendered across four variants and five states
variant \ state defaulthoverfocus disabledloading
primary
secondary
ghost
destructive
interface ButtonProps {
  variant?:  'primary' | 'secondary' | 'ghost' | 'destructive'
  disabled?: boolean
  loading?:  boolean
  label:     string
  icon?:     IconName
  onPress:   () => void
}
// variant, disabled and loading are props.
// hover and focus are CSS states — never props.

Generative surface 3 props + 2 CSS states
→ 20 cells
variant (4) × state (5)
= 20 rendered cells
from one styled component.

Component
Button
Props
variant · disabled · loading
Rendered states
20 · 4 variants × 5 states
The Button component from the Pawmates design system, rendered live across every variant and state combination in the as-built tokens rather than this site’s palette. Hover and focus are deliberately CSS states rather than props, which keeps the component API at three inputs while the visual surface covers twenty cases.
DESIGN SYSTEM Brand guideline Pawmates tokens FIG C

Rendered from the tokens, not transcribed

The guideline reads the same tokens the product reads, so it can’t go stale.

Every swatch, size and ratio below is resolved at render time from the token declarations. The hex labels and the contrast numbers are computed rather than typed, so changing a token changes the guideline with it.

The binding
swatch: { backgroundColor: T.purple }
label:  { color:       T.purple }

The swatch fill and this label’s text read the same var(). Change the token and both move together — a stale value is structurally impossible, not merely discouraged.

As-built reconciliation: the design-system document specified #6B3FA0. The shipping app used #7828F0. The token file follows the app, because the document was the stale one. The profile-chip palette was undocumented entirely and was recovered by sampling the build.

Type scale — font-size: var(--text-*)
Display--text-display · 44 / 700
Heading--text-heading · 32 / 700
Title--text-title · 22 / 600
Body copy for reading--text-body · 15 / 400
Caption--text-caption · 13 / 500
MICRO LABEL--text-micro · 11 / 600
Colour set — background: var(--*)
purple
#7828F0
purpleDark
#5512C4
purpleLight
#EFEAFE
purpleMid
#9678D2
pink
#E8449A
orange
#F5A623
red
#EF4444
dark
#1A1A2E
white
#FFFFFF

Contrast · WCAG 2.1 · computed from tokens · pass/fail marked in text, not colour

dark · whiteAAAAA
purple · whiteAAAAA
purple · purpleLightAAAAA
orange · darkAAAAA
orange · whiteAAAAA
red · whiteAAAAA
pink · whiteAAAAA
Spacing ramp — width: var(--space-*)
--space-1 · 1px
--space-2 · 2px
--space-3 · 3px
--space-4 · 4px
--space-6 · 6px
--space-8 · 8px
--space-12 · 12px
Source
Token declarationsthe same custom properties the product renders from
Coverage
type · colour · spacingas-built v0.8
Guarantee
A view, not a copyit cannot drift out of date
The Pawmates brand guideline. Values are the as-built v0.8 tokens; hex labels and WCAG contrast ratios are computed at render time from the resolved values rather than typed, which is how the reconciliation above was found in the first place. Several real pairs fail AA and are marked as failing.
Range

Ward 8 — campaign intelligence

A data-driven strategy brief for a municipal council race: turnout and demographic analysis, incumbent-vulnerability assessment, and an electoral-math case for a winnable path.

Sead — functional-ingredient system

Mapped 38 functional ingredients across a wellness restaurant's menu into a dual-audience interactive reference — clinical for staff, plain-English for guests.

The method travels beyond design — research, strategy, and systems, applied wherever the edge is.

What partners say
We have worked together on Pawmates for over 5 years. Isaac has grown in that span exponentially to reach a level of agency and judgement of a true Product leader. I listen to his judgement and acknowledge that his signal-to-noise work ethic made him instrumental to our start up. Truly a great Product Design Founder.
Colin Jarvis-Gaum · Founder, Pawmates
When I first met Isaac I was unsure on why he’d want to work with me on resolving a unique real estate problem, moving this hard to sell property. After some conversations about what my problem was, where I wanted to go and some research together, he came up with a solution to not only one but three common real estate problems.
Kari Estrada · Century 21 Heavenly, Los Cabos
Let's talk

Need one person to own design, build, and the result?

Isaac Sven ManzanarezProduct designer · Connecticut · New York metro

BasedConnecticut · New York metro
AuthorizationCanadian · TN-eligible (Industrial Designer, USMCA)
For an employerNo H-1B lottery, no petition fee
Open toProduct design roles — CT, NYC metro, remote