Jorge Molina

Personal Project · May 2026

PickPal

Built a web app that generates AI-powered personalized gift ideas matched to the person, occasion, and budget, from idea to private beta in 7 days.

Role

Product Designer · directed the full-stack build with Claude Code

Tools

Figma · Claude Code · Next.js · Convex · Clerk · Gemini 2.5 Flash · Resend

From idea to production

7 days

Private beta users

10+

Executive Overview

PickPal helps you land on a thoughtful gift for the people who matter, every time. It centralizes who they are (interests, notes, sizes, important dates) and, when an occasion nears, generates AI ideas matched to that person, occasion, and budget. Designed end to end, then directed the full build with Claude Code: design system, copy, and full stack, shipped to a private beta of real users.

The Problem

Two chained problems: forgetting the date (you're reminded the day of, too late for anything thoughtful) and, even in time, not knowing what to give. Decision paralysis pushes you to a generic, last-minute pick.

The Solution

A web app pairing a date tracker with an AI gift advisor: add the person, the occasion, and the budget, and get 9 personalized ideas with direct links to buy.

Product Thinking

The Core Insight
The real pain isn't forgetting, it's the decision paralysis that comes after you remember. Phones already solve the reminder problem. What nobody had built was the layer between "I know it's their birthday" and "I know what to give them."

Where the idea came from

PickPal started as my own problem, and informal conversations with friends and family kept surfacing the same pattern: the hard part was never remembering, it was deciding. Before writing any code I mapped how people patch this today (phone reminders, wishlists, a last-minute search), and none closed the loop from knowing the date to knowing the gift. Lightweight validation, not formal research, but consistent enough to build on.

Existing Alternatives & Their Gaps

Of the four common workarounds, only PickPal covers the full chain: from anticipating the date to a concrete idea that fits the person, occasion, and budget.

CapabilityPhone remindersAmazon WishlistsGoogle searchReminder appsPickPal
Reminds in advance
Suggests gift ideas
Keeps the surprise
Personal context (interests, sizes)
Aware of occasion & budget
Learns from your usage

Target User

The Thoughtful Gifter

Family, partners, close friends

Profile

Someone who invests in their relationships and wants their gifts to mean something. Not a productivity tool or a CRM, they want to come through for people.

Goals

  • Give thoughtful, personal gifts
  • Anticipate dates that matter
  • Have the gift say something about the person

Frustrations

  • Decision paralysis when it matters most
  • Generic, last-minute picks

From Idea to Product

One shape, almost obvious from the insight: a date tracker plus an AI gift advisor, so the tool that remembers is the one that decides.

Deliberately not a CRM, not a productivity app, not a social network — those framings pull a product toward cold contact lists and dashboards. PickPal is a warm notebook for the people you love, and every later decision had to defend that line.

Directing the build, not writing the code

I'm a product designer, not an engineer. I owned the product, design, and architecture calls; Claude Code wrote the implementation. The intent never left my hands, so what I designed is what shipped.

The product needed four things, so I picked one tool for each:

Store the data

Convex

Real-time database, no loading states to design

Accounts & security

Clerk

Sign-in and account management, out of the box

Generate the ideas

Gemini 2.5 Flash

Fast, low-cost AI model

Event reminders

Resend

Email service to alert before each date

Seven days, first commit to private beta

7 days
  1. 1

    Map the problem

    Lightweight validation, before a line of code

  2. 2

    Brief and design language

    A warm notebook, not a SaaS dashboard

  3. 3

    Full-stack build

    Next.js · Convex · Clerk · Gemini · Resend

  4. 4

    Private beta

    May 11, 2026 · 10+ real users

Design System & Visual Identity

Concept & Intent

PickPal is about people you love and occasions that matter, so the references were not productivity tools: they were Things 3, personal Notion, quality stationery. The brief I set myself: a warm paper notebook, not a SaaS dashboard.

Deliberate positioning, not taste: I design dense B2B dashboards every day at Wakyma, and an emotional product asks for the opposite. The bet: if it feels like opening a notebook rather than logging into a tool, it stands apart from anything the user has tried.

References were Things 3, personal Notion and quality stationery, never Linear, Material or Stripe Dashboard. A warm paper feel over cold grays and corporate gradients.

The design-system board: the same OKLCH tokens in both modes, aged paper in light, deep warm brown (never black) in dark.

Color Palette

All colors defined in OKLCH for perceptual consistency between light and dark modes.

#FBF7EE

Warm cream

Background

Evokes slightly aged paper, not clinical white

#2D4033

Forest green

Primary

Grounded, natural-warm, not "eco startup" green

#D97757

Terracotta

Secondary / Accent

Warm accent for relationship badges and emphasis

Dark mode uses a deep brown background (not black) and a cream foreground (not white): reading by lamplight, not staring at a terminal. The terracotta accent stays fixed in both modes.

Typography

Two typefaces with distinct, non-overlapping roles:

TokenFamilyUse
--font-headingFraunces (serif)h1, h2, h3, impact, personality, brand character
--font-sansGeistEverything else, UI, body, forms, navigation

Fraunces brings warmth and character at large sizes (the "quality stationery" feel), but hurts readability in long text, hence the rule: impact, not blocks of reading. Never serif in buttons, badges, nav, or any text over 2 lines.

Component Decisions

Three patterns from docs/design-system.md: the paper lifts on hover, empty states speak with a human voice, and saving needs no button.

Cards, "The paper lifts"

Fully clickable cards lift on hover: a subtle upward translate plus a shadow bump, like a sheet of paper lifted from a surface, not a dramatic float. Cards that aren't fully clickable get only `hover:shadow-md` (no translate), so it's never unclear what a click does.

Empty States, Human voice, not system labels

Each empty state has a name and personality: no contacts → "A blank notebook," no upcoming dates → "All quiet." Dashed border, a decorative emoji (the only place the app uses them), a serif headline, and a CTA that drops the user exactly where they need to be.

Autosave Profile Editing, No Save Button

The profile has no save button: every field saves on blur, and a small "✓ Saved" pill appears bottom-right for 2 seconds. No noisy toasts, no dirty-state, no navigation guards: edit it like a note, it saves, move on.

Voice & Copy

Yes

"The people who matter to you," "your loved ones," "a thoughtful detail," "all quiet ahead"

No

"Your contact list" (cold, sounds like a CRM), "AI-powered smart notifications" (jargon), gratuitous exclamation marks, emojis in buttons or cards

Yes

Nav label: "Loved ones"

No

"People", it's a positioning statement, not just a semantic choice

Documented Anti-Patterns

  • Gradients on large surfaces: broke the warm paper feel immediately
  • Traditional form with dirty tracking + Save button for inline editing: unnecessary friction for a profile that should feel like a note

How It Works

PickPal follows a three-step flow that turns what you know about the people you love into concrete, ready-to-buy gift ideas.

Step 01

Add your loved ones

Create a profile for each person who matters: name, relationship, interests, free-form notes, sizes, and things they don't like. Everything in the profile feeds the generation prompt: interests steer what the AI suggests, dislikes steer what it avoids.

Step 02

Track their dates with budgets

For each person, add the occasions you want to remember, birthday, anniversary, graduation, or any date that matters to you. Each occasion has its own budget: you can spend differently on the same person's birthday and at Christmas.

Step 03

From the agenda to 9 ideas in one click

The dashboard lists every upcoming date ordered by days remaining, with a 30 / 60 / 90-day filter and optional email reminders. Open one, pick the gift type (physical product, experience, time together, or surprise me), and the AI returns 9 ideas tailored to that person, occasion, and budget, each with a short rationale, price range, and chips straight to the most relevant stores.

From every card you can save it, discard it, or jump straight to the store of your choice.

Key Product Decisions

The 9-ideas grid after a generation (high-fidelity mockup; product UI in Spanish): price aligned across each row, 1–3 store chips per idea, 👎 discards and the AI learns.

Budget per Occasion, Not per Person

Each important date has its own budget range: you spend differently on a birthday and on Mother's Day for the same person. The AI gets a per-occasion budget signal too, so ideas land far closer than a generic "up to €50" applied to everything.

Four Gift Types

The type selector (Physical product / Experience / Time together / Surprise me) changes both the AI prompt and the stores shown on each card. "Time together" costs nothing (plans, handmade things); "Experience" suggests restaurants, workshops, trips. Because for many people the best gift isn't something you buy.

Smart Discard with Category Memory

A thumbs-down stores the exact title (so it's never literally regenerated) and the idea's categories, accumulated across that person's discards and capped at 100. The next prompt feeds those back as "gifts that don't work for this person": it learns the pattern behind rejections, not just the skip.

Rate Limit That Doesn't Punish Errors

10 generations per user per day, but the counter only increments on a successful Gemini response. If the API fails mid-request you retry without losing quota. That needed a two-step flow (check quota → call Gemini → consume on success) so users aren't penalized for infrastructure failures outside their control.

Multi-Store Search with Per-Idea Intelligence

Each idea shows 1–3 store chips the AI picks for that specific idea, not a global preference: a "local artisan honey" won't suggest AliExpress, a "gaming peripheral" won't suggest Zalando. The chips shown are the intersection of the AI's pick and your preferred stores (Settings), with a clear notice if there's no overlap.

11 stores: Amazon, El Corte Inglés, AliExpress, Temu, Miravia, Decathlon, IKEA, PcComponentes, MediaMarkt, Zalando, Druni.

Technical Highlights

I don't write code, so these were the architecture calls I drove while directing the build with Claude Code. Each one was a product decision as much as a technical one.

The generation pipeline: LLM output treated as untrusted input, with three validation layers between Gemini and the database.

Zero loading states to design (Convex)

Real-time reactivity meant no spinners or stale states to design: upcoming dates and saved people stay current on their own, so the app feels instant. Convex queries update without polling and the schema is native TypeScript, with no ORM layer.

For a product where "your upcoming dates" needs to feel instant and always current, this was the right architecture.

Trust from the first screen (Clerk)

The first screen a user ever sees is sign-in, so it has to feel trustworthy. Clerk ships polished sign-in, sign-up, account management and Google OAuth out of the box; NextAuth would have meant building those screens myself.

With a 7-day runway to production, that difference is decisive.

Suggestions that never arrive broken (Gemini 2.5 Flash)

Validating the AI response against a Zod schema means the user never sees a broken or half-formed result: the 9 ideas always arrive in the same clean shape. That reliability is a UX decision, not a technical one.

Flash is fast and cheap enough: 10 daily generations per user cost under €0.01/month at current beta scale.

Trust in the AI, enforced in three layers

Treating the model's output as untrusted input, the same as a user-submitted form, is what keeps the experience safe: every suggestion is verified before it reaches the screen, and nothing the AI writes can hijack a store link.

Zod validates field types and store IDs against the allowlist. The Convex mutation validator re-validates sizes, ranges, no duplicate titles, exactly 9 ideas, closing the gap for an authenticated attacker calling the mutation directly. encodeURIComponent prevents injection from AI-generated queries into store search URLs.

Beta & Learnings

PickPal launched to private beta on May 11, 2026, one week after the first commit. A closed group of friends and family is using it in real conditions; their feedback drives the iterations below.

Closed beta study: friends & family

Rather than a casual "try it and tell me", I ran the private beta as a small but structured study, so the feedback would be actionable and the bias honest.

What I wanted to learn

Do people grasp what PickPal is and who it’s for within the first minute, with no explanation?

Can they complete the critical flow (add a loved one → generate 9 ideas) without getting stuck?

Do the generated ideas feel personal and useful, or generic?

Where does friction or doubt appear in real conditions (mobile, in a hurry, incomplete data)?

Participants & recruitment

12

close users

24–58

age range

2

gifter profiles

A purposive convenience sample, close on purpose: a short beta needs real, sustained use (a genuine birthday next week) and unfiltered feedback. The two profiles cover the behaviours that matter: last-minute "impulse" gifters and early planners, all daily smartphone users.

How I invited them

A deliberate onboarding to set expectations and get consent, like a company beta:

Invitation email (via Resend, the product’s own infrastructure): what PickPal is, the ask (use it for one real gift over two weeks), the ~10-min setup, and that their feedback would shape the product.

One-page brief: think aloud, don’t protect my feelings, the bug you hit is gold, plus consent to log usage and quote feedback anonymously.

Staggered access in two waves (6 + 6, four days apart), so I could fix anything critical before wave two.

How I collected feedback

Passive and active channels, every entry tagged by screen, severity and frequency so prioritisation was data-driven, not whoever-complained-last:

In-app feedback: a persistent "Tell me" button on every screen, capturing the route, device and comment into a Convex table with a timestamp.

Lightweight diary: a WhatsApp group where I asked for a message whenever something "slowed you down or made you smile": very low friction, high volume.

3 short calls (15 min) with the extreme profiles, watching them use the app on their own phone (moderated, no rigid script).

Exit micro-survey (4 questions, scale + open) at the end of the two weeks.

From feedback to iterations

I grouped ~40 observations by affinity and prioritised them with an impact × effort matrix, then iterated live: after each change, the person who reported it re-tested it, closing the loop. Four changes that shipped during the beta:

What I observedWhat I changed in the appIteration
Filling a loved one’s tastes from a blank field was slow, and the thinnest profiles produced the most generic ideas. Several testers added one or two tastes and stopped.Added taste suggestions inferred from what’s already saved for that person, plus type-ahead autocomplete, so adding a taste is one tap, not a free-text chore.
Testers with a brand-loyal loved one ("he only wears Nike", "she always buys at Sephora") found generic ideas useless and kept asking where to actually buy them.Added favourite brands per loved one (logos pulled via the Brandfetch API). Ideas tied to a saved brand now show a dedicated button that opens that exact store with the search already applied.
Text-only idea cards felt flat and made each idea hard to picture at a glance.Integrated the Pexels API to attach a stock image matched to each idea’s name; when no good match exists, the slot falls back to a representative icon instead of an empty frame.
Opening "generate ideas" from a loved one’s profile (not from the agenda) preselected no occasion and left the generate button disabled, so testers thought the app was broken.Now a single upcoming event is preselected automatically; with several events the button stays active and, on tap, prompts the user to choose which occasion to generate for.

Limitations

Small convenience sample (n=12): detects obvious friction and validates the flow, not market demand.

Social-desirability bias: mitigated by asking for "the flaw, not the praise", observing real use over stated opinion, and weighting behaviour over claims.

Short horizon (2 weeks): measures first experience, not retention.

Key Learnings

Design for two distinct emotional states

Two very different moments: calm setup (creating a profile, adding dates and interests) and urgency mode (the birthday is tomorrow, I need an idea now). The UI has to serve both: the first patient and exploratory, the second frictionless and fast.

Voice is product positioning

"Loved ones" vs "Contacts" isn't a copy decision. It's a statement about what PickPal is and who it's for. Every label, empty state, and button can reinforce or erode that, so the voice rules live in the design system to keep them from diluting as the product grows.

Directing the build keeps the design intent intact

I don't write code, so I directed the whole build with Claude Code, from design tokens to database schema. Holding the intent end to end removes the translation loss between what's designed and what ships. The flip side: the temptation to keep iterating technically instead of watching users. The most important work after shipping is listening, not refactoring.

Document decisions as you make them

Every non-obvious choice carries a "why": not just what was decided, but what was rejected and why. In three months that reasoning would be opaque; writing down the rejected options is what makes the system reviewable instead of a matter of taste.