The Portfolio as Product: Building royvillasana.com with AI at Every Layer

Role: Designer, engineer, and product owner · Timeline: October 2025 – February 2026 (18 weeks, solo project) · Year: 2026 · Domain: AI Product Design

TL;DR: Designed and built an AI-native portfolio where a voice and text-driven Generative Canvas rebuilds itself in real time from visitor queries, backed by a prototype-first design system derived from working code via Pencil.dev. Average session duration is 3.4 minutes — nearly double the 1.8-minute industry benchmark for portfolio sites — with the Generative Canvas receiving an average of 4.6 queries per session and voice mode adopted by 31% of returning visitors.

royvillasana.com is a fully AI-native portfolio: a conversational canvas that rebuilds itself from voice or text queries, a design system built prototype-first through Pencil.dev, and Claude as the intelligence layer throughout. Built to demonstrate the methodology while you navigate it.

Impact

The Brief: Portfolio as a Living Product

Most portfolios are static documents — a curated gallery of past work with a PDF resume attached. That model has a fundamental problem: it tells you what someone made, but not how they think.

The brief for this project was different from the start: build a portfolio that demonstrates the methodology while you navigate it. A product designer who works at the intersection of AI, systems thinking, and code should have a portfolio that proves all three — not one that describes them.

That constraint shaped every decision: the architecture, the design process, the tooling, and the interactions. The portfolio had to be AI-native — not AI-flavored.

The AI-Driven Generative Canvas

The centrepiece of the portfolio is what I call the Generative Canvas — a dynamic workspace that rebuilds itself in real time based on what the visitor asks. This interaction model has a specific name in the AI product design field: Generative UI (sometimes called Streaming Generative UI or AI-Orchestrated Rendering).

The pattern works like this:

  1. The visitor types or speaks a query — "Show me your systems design work" or "What's your approach to AI research?"

  2. The query is classified by an intent engine built on Claude

  3. Claude generates a structured Render Plan — a JSON object specifying which UI modules to show, in what order, with what data

  4. The canvas re-renders with those exact modules: project grids, case study viewers, impact tables, timelines, evidence rails

What makes this different from a chatbot is that the answer is the UI itself. There is no text response saying "here are my design systems projects" — the canvas just shows them. The intelligence is expressed through layout and content, not through prose.

The render plan engine supports over 15 module types, 8 intent categories, and a scope detection layer that distinguishes between broad portfolio queries and deep project dives — routing each to the right presentation recipe.

Live Voice Mode: Adaptive UI Through Speech

The voice layer extends the Generative UI pattern into a continuous, hands-free experience. When Live Voice Mode is active:

The ambient visual system responds to what's happening: a green glow pulses around the viewport in idle state, shifts to a heartbeat rhythm when the AI is speaking, and intensifies its wave amplitude proportional to the length of the transcript — longer speech produces larger, faster waves. This is not decoration — it's a real-time feedback layer that tells the visitor exactly what the system is processing.

Technically, this required solving two non-trivial problems:

1. Conversational query preservation. When a visitor asks a follow-up question about a project already on canvas ("What tools did you use for that?"), the system detects the conversational intent and answers in chat without resetting the canvas. An intent classifier using regex patterns and absence-of-navigation keywords routes these to a chat-only response path.

2. Spring-driven animation in a nested scroller. Framer Motion's whileInView hook uses the window viewport as its IntersectionObserver root. Inside a nested overflow-y-auto canvas panel, off-screen blocks never trigger — staying at opacity: 0 indefinitely. The fix: replacing whileInView with animate so blocks render on mount with a staggered entrance, not on scroll position.

Design System: Prototype-First with Pencil.dev

The conventional design workflow runs in one direction: Figma → Code. Define the system in the design tool, implement it in the codebase, maintain two sources of truth forever.

This project ran it in reverse.

I built the working product first — directly in React and Tailwind, in the browser, with real data and real interactions. Only once the product felt right — the layouts, the spacing, the component boundaries — did I move into Pencil.dev.

The process:

  1. Prototype in code until the design decisions stabilised. No Figma. No wireframes. Just the real product.

  2. Import into Pencil.dev once the visual language was settled — translating the working UI into a structured design file.

  3. Extract the system — components, tokens, spacing rules — from what the code had already decided, not from an abstract ideal.

  4. Connect to GitHub — Pencil.dev's GitHub integration means every change to the design file propagates automatically. The design system and the codebase stay in sync without manual export/import cycles.

The result is a design system with 20 reusable components — Sidebar, ProjectCard, BlogCard, AIResponseCard, ServiceCard, TimelineEntry, CTABanner and more — all derived from a product that was already working, not from a designer's ideal vision of what it should be.

This matters because design systems extracted from real products have one property that systems designed top-down rarely achieve: every component has already survived contact with actual content.

AI-Assisted Design with Pencil.dev + Claude

Pencil.dev uses Claude as its generation engine. This changes the design loop in a specific way: instead of drawing components, you describe what you need, and Claude generates a design that is fully editable — every node, every property, every constraint — exactly like a component you drew by hand in Figma.

The practical implications:

This doesn't mean Figma disappears from professional workflows — it means the threshold for when it adds value rises. For solo projects and small teams moving fast, Pencil.dev + Claude + GitHub is a complete design pipeline.

Technical Architecture

LayerTechnologyRole FrontendReact + TypeScript + ViteComponent architecture and build pipeline StylingTailwind CSS + shadcn/uiDesign token system and UI primitives AI EngineClaude (via OpenRouter)Intent classification, render plan generation, chat responses DatabaseSupabase (Postgres)Projects, posts, site settings, translations VoiceWeb Speech APIContinuous speech recognition and interim transcripts AnimationFramer MotionCanvas transitions, voice ambience, persona halo Design SystemPencil.devComponent library synced to GitHub HostingVercelCI/CD from main branch, edge deployment Localisationi18next + Supabase translationsEN / ES / FR / PT across all content

The AI intent classification pipeline works in three stages: scope detection (single project vs. portfolio overview), intent classification (8 categories including SHOW_CASE_STUDY, SHOW_SKILLS, GENERAL_QUESTION), and render plan building (selecting the right module recipe and populating it with live Supabase data). The full round-trip from query to updated canvas averages under 2 seconds.

Key Learnings

Build the product before the system

Starting in code rather than Figma produced a design system that reflected real decisions, not hypothetical ones. Every token and component exists because the product needed it — not because a design system checklist said it should.

Generative UI requires a strong render plan model

The temptation with LLM-driven interfaces is to let the model decide everything. The portfolio works because the render plan is structured — the AI classifies intent and selects recipes, but the module types, data shapes, and layout rules are defined in code. AI fills the system; it doesn't replace it.

Voice changes the experience more than expected

Live Voice Mode started as a feature. It became a framing device. Seeing someone navigate a portfolio by speaking to it — watching the canvas rebuild in response to their questions — communicates something about AI fluency that no case study text can. The medium is the message.

Animation in nested scrollers needs explicit viewport roots

Framer Motion's whileInView defaults to the window viewport. In any SPA with an inner scrollable panel, off-screen content stays invisible. This is a silent failure — no errors, no warnings, just blocks that never appear. Always use animate over whileInView inside nested overflow containers, or explicitly pass the scroll container as the viewport root.

Highlights

Capabilities

AI Integration, Generative UI, Voice Interface Design, Design Systems, Full-Stack Development, Design Tooling

Tools

Claude AI, Pencil.dev, React, TypeScript, Supabase, Vite, Tailwind CSS, Framer Motion, Vercel