How I Learned to Talk to Lovable AI—and Was Finally Understood

A case study on how I learned to guide AI to produce pixel-accurate, reusable results and implement my design system the way I built it in Figma.

AI-ASSISTED ENGINEERING EXPERIMENT 2026

Test Syllable LIVE

Project Team Setup

  • Me – Product Design, UX, Prompt Engineering
  • Lovable – AI Developer (Code Generation & Implementation)
  • ChatGPT – Prompt Support & Technical Sparring
  • 1:1 Design Prompting
  • Acceptance Criteria
  • Accessibility
  • AI
  • AI Workflows
  • Component Library
  • Component Thinking
  • Design System
  • Design Tokens
  • Prompt Engineering
  • Prompting
  • Spec-Driven
  • Vibe Coding
  • Builder.io
  • ChatGPT
  • Claude
  • CSS
  • Figma
  • HTML
  • Lovable
Design system overview with game UI components, states and visual elements

01 Building the UI Foundation

Core components, states and visual rules for the game.

I wanted to understand:

Can I build a pixel-precise App with Lovable AI, without losing control over my Figma design, structure, and logic?

🎯 My Goal

Build a functional mobile web app using Lovable AI and define a workflow that allows me to control the outcome. How should Figma be structured, what can be inferred from the export (and what cannot), and what instructions and rules are necessary to guide the AI toward reliable, reusable results?

👉  The Product

A simple word game, similar to charades, but limited to one-syllable hints.

Try it on your own, too, by opening two firm ones side by side

Long Story short 👇

Builder.io was able to recognize a surprising amount of this structure — including components, variants, nesting, Auto Layout, colors and many design values. The key learning: design the Figma file with implementation in mind and remove as much ambiguity as possible before exporting.A clean Figma file makes a huge difference — the more explicit the design system, the less the AI has to interpret.

What worked best: clearly named and grouped components, consistent variant logic, explicit design tokens, Auto Layout throughout, mobile-first screen design, defined breakpoints and states, and separate Builder.io exports for relevant breakpoints or variants.

 

The cleaner and more implementation-friendly the Figma file, the easier the handover to Builder.io and Lovable became.

  1. Keep the structure simple.
    Avoid unnecessary frames or complicated nesting. Build the layout as closely as possible to how it could later work in real CSS.
  2. Use Auto Layout consistently.
    Define clearly how elements behave: fixed, hug, fill, spacing, alignment and responsive resizing.
  3. Name everything clearly.
    Components, variants, frames and important layers should have understandable and consistent names. Good naming also makes it much easier to reference them later in prompts.
  4. Build reusable components only once.
    Create components and variants centrally and reuse them throughout the design instead of rebuilding similar elements inside individual screens.
  5. Define variants and states before the handover.
    The more complete the component system is in Figma, the fewer decisions the AI has to make later.
  6. Think about the code structure while designing.
    Figma and CSS do not behave exactly the same. If I already know that a certain structure can create problems in code, I can adjust the Figma structure before exporting. → See also: Figma ≠ Real CSS Findings
  7. Do not rely on the generated code alone.
    For more complex structures, I sometimes also provided a screenshot of the Figma layer/component hierarchy and explained how the elements were meant to be nested and reused.
  8. Make the structure easy to explain.
    A good test was: Can I quickly show the Figma structure and explain how the page is built from components, variants and containers? If yes, the AI handover was usually much easier.

Main learning:
Build Figma not only for the final visual result, but also for a clear handover. Simple structure, consistent naming, reusable components and explicit hierarchy reduce the amount the AI has to interpret.

A design can be perfectly valid in Figma and still require a different structure in real CSS.

Things I had to learn and correct: Figma auto line-height can turn into incorrect framework defaults, fill + max-width does not behave the same in CSS, stretched components can break centering, visual layer order does not automatically become z-index, and gradient strokes need a different CSS implementation such as layered backgrounds.

Sometimes I even had to restructure the Figma component — for example by introducing wrappers — to make the design reflect how the layout actually needs to work in code.

Big learning: pixel-perfect AI handoff also requires some understanding of real frontend constraints. Generated code still needs to be inspected and challenged.

At first I thought Lovable had failed to create my component system because I could not see the Figma component names in the browser inspector.

But React components are compiled into normal HTML elements when rendered — so the original component structure is not automatically visible in the DOM.

My solution was to make the system explicitly inspectable:

data-component="ComponentName" → identifies the React/Figma component
data-typo-token="text-m" → identifies the typography token being used

This turned the DOM into an additional validation layer: I could inspect a screen and verify which component and token was actually being used instead of trusting the AI’s description of its implementation.

Learning: if AI-generated systems need to be validated by a designer, build observability into the implementation.

During the project, I learned how easily small gaps in a prompt can turn into unwanted AI decisions.

  1. Leaving too much room for interpretation
    A general idea is often not enough. If I do not define the behavior clearly, AI fills the gaps itself. I need to think through the task more like a design or development ticket: What happens when? What if X happens? What if it does not? Which states, conditions and edge cases exist? What should never happen?

    Clear acceptance criteria are important: How should something work, and how do I know when it has been implemented correctly?

  2. Changing the focus by accident
    The wording of a question can change the priority. When I asked for the fastest handover, the conversation shifted toward speed — although my actual priority was pixel accuracy. AI reacts strongly to the current request, so the main goal needs to stay clear.
  3. Not making important rules strict enough
    I originally wrote: “Use the following breakpoints across the entire app” and listed my S / M / L values. Lovable still used Tailwind defaults.

    Only after I explicitly wrote “BREAKPOINT SYSTEM MANDATORY — use exactly these breakpoints” did it follow my system.

    If something is non-negotiable, I need to say so clearly.

  4. Not defining the role and source of truth clearly enough
    AI needs to know what its job is and which source it must follow.

    In my case, Builder.io code became the single source of truth for layout, structure, hierarchy and design tokens.

    “Do not guess” alone was not enough. I had to make the role explicit:

    You are not designing. You are not interpreting. You are building.

    If several inputs exist, I also need to define which one wins. Otherwise, the AI has to decide that itself.

  5. Not asking for clarification, validation and reporting
    If something important is missing, conflicting or unclear, AI should stop and ask before building instead of making the decision itself.

    It also helped me a lot to make validation part of the prompt. After implementation, I asked the AI to go through all requirements again, check its own work, correct mistakes and then tell me exactly what it changed.

    This created another control layer before I checked the result myself.

  6. Forgetting important system rules
    AI does not necessarily notice that an instruction is missing. When I forgot to define token rules, Lovable simply created its own token system.

    If I do not want an alternative solution, the rule needs to be explicit.

  7. Giving conflicting instructions — including old ones
    Instructions can work against each other. At one point, I referred to Figma tokens while Builder.io was already defined as the single source of truth.

    I later found another problem: a strict MUST rule from an earlier instruction could override what I asked for in a new prompt.

    So I also need to check whether my current prompt, persistent rules and previous instructions still fit together.

  8. Depending too much on conversation history
    AI reacts strongly to the current input. Important goals, constraints and rules should therefore not depend only on something discussed much earlier.

    For critical tasks, I learned to treat each prompt more like a fresh handover to a new team member — or explicitly tell the AI to read the relevant instruction files again.

  9. Being too implicit about states and variants
    Defining a component and its variants was not always enough. Even if Lovable already knew a variant, it did not automatically mean that the correct one would be used in the correct state.

    I had to make the connection explicit:

    State X → Component Y → Variant Z

  10. Trusting the result without checking it myself
    AI can sound confident even when the implementation is wrong. It generates a plausible result — not automatically the correct one.

    Components, variants, tokens, responsive behavior and logic still need to be checked against the original requirements.

A useful check before sending a prompt:
Would a new developer understand exactly what I mean — or could they still ask “What happens if…?”

And before accepting the result:
Did the AI actually do what I asked — or does it only sound like it did?

Clarify → Build → Self-check → Report → Verify

The breakthrough came when I stopped treating Lovable like a conversational design partner and gave it a strict implementation system.

I defined Builder.io as the single source of truth, switched Lovable into a clear Frontend Developer / Builder role and specified rules for: tokens first, exact naming, reusable components, variants via props, nested components, no duplicates, global updates instead of local overrides, mandatory S/M/L breakpoints, responsive behavior and validation before implementation.

I then externalized the rules into three persistent files:

instructions.md → global implementation rules
component_system.md → components, variants and updates
game_rules.md → screen-specific product logic

Instead of repeating a huge prompt every time, new prompts can now reference the system, add the screen-specific context and update the documentation when something changes.

Big learning: reliable AI implementation needs a persistent system — not an ever-growing conversation.

A good prompt does not have to be short. For complex tasks, it should work more like a well-prepared design or development ticket: clear enough that the person executing it does not have to fill important gaps themselves.

For more complex tasks, I now check these ten things:

  1. Role
    Who should the AI be for this task?
    A developer, reviewer, designer, researcher or something else?
  2. Context
    What does it need to know to understand the task correctly?
    Include the relevant project context, current state and important background.
  3. Task & Goal
    What exactly should it do, and what should be true when it is finished?
    Be clear about the desired outcome — not only the action.
  4. Source of Truth
    Which information is authoritative?
    Figma, Builder.io code, an existing component, documentation or a specific file? If sources conflict, define which one wins.
  5. Scope
    What exactly may be changed?
    Name the component, variant, state, breakpoint, page or file — and also what must stay untouched.
  6. Conditions, Edge Cases & Acceptance Criteria
    Think through the task like a ticket before handing it over:
    When should something happen? What if X happens? What if it does not? What happens next? What should never happen?

    Define the important if / then conditions, states, exceptions and edge cases as clearly as possible.

    Also define the acceptance criteria:
    How do I know that the task has been implemented correctly?

  7. Rules & Constraints
    What must the AI follow?
    Define mandatory tokens, naming, breakpoints, component rules, technical restrictions and fixed requirements. Also say clearly what it must not redesign, invent, rename, duplicate or replace.
  8. References & Expected Result
    If something should follow an existing pattern, show it.
    Use examples, existing components or references and describe the expected behavior, structure and output.
  9. Clarification
    Tell the AI what to do when information is missing, conflicting or unclear:
    Stop and ask before building. Do not make the decision yourself.
  10. Validation & Self-Check
    Ask the AI to review its own work before finishing:

    Go through all requirements again. Check every condition, acceptance criterion, component, variant, token, breakpoint and behavior. Look for missing cases, conflicts or unintended changes. Correct them before reporting the task as complete. Then summarize exactly what you changed.

For complex tasks, prompts can become quite long — and that is not necessarily a problem. The important part is that the detail comes from thinking through the task, not from adding unnecessary words.

Stable project rules can live in persistent instruction or component files. The individual prompt can then focus on the current task, conditions, edge cases, scope and expected result.

Clarify → Build → Self-check → Report → Verify

And even after the AI has checked itself, I still verify important results myself.

My rule of thumb:
Before sending a prompt, ask: Could a developer still ask me “What happens if…?”
If yes, I probably need to think the task through one step further.

AI does not always need the same level of control. It depends on what I want to achieve.

At the beginning of the project, natural language worked very well. I could describe an idea, test a rough functionality, explore different directions and let Lovable make suggestions. In this phase, some interpretation was actually helpful.

  • For exploration: Natural language is often enough. AI can help generate ideas, test flows, create first prototypes and show different possible directions.
  • For early validation: A rough implementation can be more useful than spending too much time defining every detail upfront. It helps reveal missing states, unclear logic or product questions very quickly.
  • For inspiration: AI can act like a design partner and make suggestions I can review, keep, change or reject.

The situation changed once my own design was defined.

When the design system, components, variants, tokens, breakpoints and product logic were already decided, I no longer wanted the AI to interpret. I wanted it to implement.

At that point, open prompts created unnecessary decisions. A visually reasonable suggestion was no longer automatically a good result if it did not match my system.

So I started to separate the two modes more clearly:

Explore → give AI room to interpret, suggest and experiment.
Execute → define strict rules, remove ambiguity and make AI follow the existing system.

This became an important principle throughout the project:

The more decisions I have already made as a designer, the fewer decisions I should leave to the AI.

The goal was not to remove AI’s creativity completely. It was to use its flexibility when exploration was useful — and control it when precision mattered.

👉  Long Version

01 Defining Product Logic with Natural Language

Instead of writing a full spec, I explored how far I could get using only natural language — starting a conversation to define the system step by step. Here’s a simplified version of that conversation 👇

09:41
What do you need from me to build a working game app?
Game idea, structure, and basic flow. Design / Screenshots are optional.
Is it easily possible to change a simple web App with shareable link and real-time interaction afterwards to an true native app?
Yes — You have two options: 1. Installable Web App (PWA) – ... 2. True Native App (Capacitor) — ... Both work with your existing React codebase — no rewrite needed. For a real-time chat, we would need Lovable Cloud (database + real-time features)..
Does real-time, hosting or playing this app cost money?
Small apps usually stay within the free tier.
Okay — let’s build a 2-player PWA version with a Lovable Cloud Backend.
Game rules: 2 players join via a link, one starts the game and invites the other. Then both are in a live chat.
One player gets a word and has to explain it using only one-syllable words.
Everything happens live in the chat, you can type or even speak, and the other person sees single words as bubbles in chat instantly.
If Player 1 uses a word with more than one syllable, the system should highlight that word. The other player can then award a penalty point by swinging the club, and Player 1 loses a point. A new word appears, and the round continues as long as the timer is still running.
If the word is guessed correctly, the guesser gets one point and the explainer gets three points. Here, too, a new word appears for the explainer as long as time hasn’t run out. The goal is to score as many points as possible over the course of four rounds. Both players take turns explaining and guessing.
For that, I´ll need your ElevenLabs API key. Do you already have one, or should I show you how to get one?
High accuracy when speaking into the mic and ensuring that the right word is actually recognized is absolutely crucial in this game. But do we really need ElevenLabs for a simple speech-to-text feature? Is it free?
Yes, for higher accuracy with ElevenLabs Scribe, you need an API key. The difference: Web Speech API (free): .. ElevenLabs Scribe (API key required): ... For a word game where every word must be recognized correctly, the higher accuracy makes sense.
OK, here´s the API key for speech-to-text and also for sound effects for later.
Got it. Building the full game now.
11:44
Game ready: Real-time, scoring, timer and word validation included.

👉 This was enough to define a working game structure — without writing a single formal specification. After just ~2 hours, I had a first working version of the game – a solid base to iterate on:

Learning 01

👉 Lovable is powerful for early-stage ideation & rapid prototyping

  • It enables quickly validate flows, uncover needed states, and turn abstract ideas into tangible experiences.

During testing, it became clear that speech recognition wasn’t reliable enough — words were missed, misinterpreted, or even triggered without input 🚧

I went back into the conversation to refine the system — adding clearer rules and defining acceptance criteria trying to make the behavior more predictable and robust 👇

09:41
Voice input still feels unstable. Recording stops immediately.
Improved voice input stability by preventing unnecessary re-renders. Recording now stays active.
Great, this works better. Now I need a few specific improvements: – Remove the delay after speaking – Detect pauses properly so words don’t merge – Set the language to German – Improve overall recognition — input sometimes stops
Enhanced voice input latency and recognition accuracy. Reduced false outputs and improved pause detection.
Language is now set to German. VAD activated. Word separation improves as the model follows German linguistic rules. Pauses are automatically detected...
The system also needs to detect correct guesses — even with typos or punctuation.
Auto-check guesses from partial transcripts. Improved word matching logic. Correct answers are now detected even with...
Player 2 should be able to speak naturally — full sentences, emojis, not just single words. No Bubbles here for every word.
Updated input handling. Player B can now use full sentences, emojis, and voice input...
Also, rule violations need to be detected — like using parts of the actual word.
Added rule validation. Word fragments of the term being defined are detected and result in a -1 penalty.
Right now it feels like something is wrong when I activate the microphone — it suddenly turns red. Please make the button green in active state. It should also show some kind of audio animation or visualization when speaking.
Updated microphone feedback. The button now turns green in active mode to indicate recording instead of an error state. Added audio visualization while speaking.
Oh what´s that? It’s just constantly flashing now. It feels really distracting. Please stop it.

👉 Up until this point, using natural language had worked surprisingly well. Then I hit this:

I asked for an “audio animation and visualization when speaking” — just to quickly make the game feel alive.

But what does that even mean? A waveform? Pulsing circle? Subtle glow? Full visualization? And what happens to the rest of the UI? Placeholder? Live transcription? Recording state?

I didn’t decide. So the AI did. (see green blinking button above)

A developer would´ve said “This needs a proper ticket.” Lovable just shipped an interpretation and filled the gap with SOMETHING.

Learning 02

👉 Natural language works — until ambiguity starts.

  • The more open a task is (especially in UI Design), the more precise your input needs to be — otherwise AI fills the gaps.
  • Treat prompts like a design brief: define states, behavior, and UI impact. Don’t leave decisions open.

Before moving into visual design, I focused on one critical issue: voice input and output. In this game, every word matters — so the system needed to be reliable enough for real gameplay. I tested how far I could push it 👇

09:41
There are still major issues with voice input/output. The system generates phantom outputs: – silence gets interpreted as actual words (like “thank you” or “goodbye”) – strange symbols or broken characters – interpreted sounds like “*kissing noises*”, “he exhales deeply”, or “whistling”
We could reduce some of this by switching to push-to-talk instead of always-on listening… or by buffering words before confirming them… but I still need much higher accuracy.
These are known limitations in speech recognition systems. Background noise, silence, or unclear input can lead to hallucinated or unintended transcripts.
That’s a problem. In this game, every word matters. I need a 100% reliable system — otherwise it creates frustration and breaks the gameplay. Can this be fully prevented?
Advanced systems like ElevenLabs Scribe v2 improve accuracy significantly (~95–98%) and include features like audio event detection and voice activity detection…
We can further improve reliability with techniques like: – Voice Activity Detection (ignore silence) – Confidence filtering – Minimum input thresholds – Confirmation logic before accepting input – Noise reduction… Push-to-talk can eliminate most phantom inputs… but 100% accuracy is not possible with any STT system.
Got it. So even with better systems, 100% accuracy isn’t guaranteed. For now, I’ll remove voice input for this game.
But let’s try a different approach — can we add a text-to-speech voice instead? Maybe something playful.
Sure — a voice output can be added. A playful voice is now configured.
I don’t hear anything.
Your ElevenLabs free-tier account has been restricted due to unusual activity. This can happen when using APIs through shared environments like cloud servers or proxies…
Alright, got it. Then let’s remove voice features completely — no speech input, no voice output. Just a clean text-based input for both players.
Voice features removed. The game now relies entirely on text input for a more stable and predictable experience.

At this point, I stopped chasing the perfect solution. The voice to text feature introduced too many external dependencies — and free-tier limitations (e.g. ElevenLabs) made it unreliable for my gameplay.

✂️ So I simplified the product: removed all voice features and focused on a stable MVP that actually works.

Learning 03

👉 Know Your API Limits Before Building

  • Free tiers often come with limitations that can break your product. Evaluate third-party constraints early — including quality, rate limits, and feature restrictions — before integrating them.

👉 Entering the Visual Layer

The game logic was working well enough for now, so I shifted focus to visual exploration.
I wanted to understand how far a single — but precise — text prompt can control visual output.

This time, I refined the prompt first — using ChatGPT to clarify effect terminology and remove ambiguity before passing it on 🎯

13:37
Create a modern mobile app background with an interactive aurora gradient. Style: warm earthy stone colors inspired by terracotta, clay and sand.
Colors: #3B1F14, #6B3A22, #C96A2B, #E88A3D, #F2C078
Design: soft mesh gradient with large blurred color blobs.

Interaction: when the user moves the mouse, a subtle spotlight / gradient glow follows the cursor and shifts the colors slightly.

The movement should feel smooth, organic and slow, like light moving over stone.

Add very subtle grain texture to make it feel natural and tactile.

Overall style: modern 2026 UI design, warm, playful, slightly primitive stone aesthetic.
Add subtle noise texture (3–5%).
Enhance aurora background.
Noise texture set to ~4% opacity with a “mix-blend-overlay” blend mode – subtle and natural.

👀 I took a closer look at the result and checked whether my defined color values were actually used — and they were. 👉 But not in a literal way. The AI adapted, softened, and blended them to create a more balanced and visually pleasing composition.

Learning 04

👉 AI listens, executes, and tries to make things look right.

  • In a way, AI behaves like a good design partner — And that’s powerful for exploration!

But what happens when I don’t want interpretation — when I already have a clear design in mind? Let’s take it one step further 👇

13:37
The screenshots of the following Figma screens are the source of truth. Recreate the layout as closely as possible. Do not introduce new styles, spacing, or components unless explicitly specified.
Please keep the aurora background effect.
On screen one, player 1 enters a name. As you see, the active state has a yellow border. Button is disabled until a name has been entered.
At the top, there are two avatar bubbles where player 1 selects their gender. The selected one is also highlighted with a yellow border.
On screen two, player 1 has already entered their name. The primary button is now active, the input is filled and inactive.
On the third screen, there is a rotating purple-yellow gradient outline while waiting for player 2.
The link needs to be copied and shared.
Redesign Home & Game screens
- Generate caveman character images
- Redesign Home screen per Figma
- Redesign waiting screen per Figma
Rebuilt the screens based on your references.
- Home: Caveman avatars with a “You?” / “You’re it?” toggle (orange ring = active), ‘EINSILBI’ title in Bungee Shade font, three rule cards, a warm name input field with an orange border + a purple “Start New Game” button
- Loading screen: Both characters side by side, player name in large block letters, rotating purple-orange border around the second avatar (indicating loading), large “Copy and share link” button
Aurora background remains on both screens

Ok, not bad. Some logic was understood — like some basic structure and interaction states — but even with visual references, I’m forcing the AI to interpret rather than replicate.

Learning 05

👉 The system cannot extract exact values from screenshots

  • Fonts, colors, spacing, and dimensions are interpreted — not read
  • Visual styles are translated into general categories (e.g. “playful”, “clean”, “modern”)
  • Custom design gets approximated into generic solutions
  • Works for simple layouts — breaks with distinctive design
Learning 06

👉 When information is missing, AI fills in the gaps with probabilities

  • Missing details are silently filled in and will be recreated somehow
  • Precision requires explicitly defining what must NOT be guessed

But what does a pixel-perfect and fast AI workflow actually look like?

I wanted to understand what it actually takes to get a pixel-perfect result. So instead of guessing, I asked the AI directly what it needs to replicate designs accurately. Below is a shortened version of that conversation👇

What’s the best way for me to hand over you my Figma designs if I want them to be implemented exactly as they are? What’s the perfect prompt for you to ensure that the components are actually set up as a component system, and that all variants of each component—and really everything—are implemented exactly as they are? What’s the best way to do this?
Step 1 — Design Tokens:
Provide colors, typography, spacing, and radius as screenshots or values. Then ask: “Please define all design tokens in index.css and tailwind.config.ts.”
Step 2 — Components:
Share one component at a time — including all variants and states. Ask: “Create this component with exactly these variants. Follow the design pixel-perfect.”
Step 3 — Screens:
Once components are ready, provide full screens. Ask: “Rebuild this screen pixel-perfect using only the defined components.”
Important details to get accurate results:

- One message = one component
(don’t send everything at once)
- Always provide exact values
(e.g. padding, radius, spacing, colors)
- show all component states
(hover, active, disabled)
-Show responsive breakpoints
(mobile, tablet, desktop)
I don’t want to take the time to hand over every component and all the values individually. Do you know of any other ways to handover you all the values as quickly as possible?
Fastest option:
Upload a screenshot and say
“Rebuild this pixel-perfect.”

I can extract colors, spacing and components directly.
👉 🦨💨💨💨💨 he can´t!
Use Figma Dev Mode:
Copy CSS values and provide them as text instead of measuring manually.
Upload multiple screens at once: 👻🙈
I can derive a full design system and build all pages from them.
Combine Figma link + screenshots:
Provide your full design system and I’ll generate components and screens.
Shortcut:
“Here is my design. Just build it.”
I’ll ask if something is missing.
Are there any Figma plugins that work well for handing over designs?
Recommended Figma Plugins:

1. Locofy.ai
• Export Figma → React + Tailwind
• Supports components & variants

2. Builder.io (Figma to Code)
• Generates React/Tailwind code
• Free version available

3. Design Tokens Plugin
• Export colors, typography, spacing as JSON
• Useful for structured systems

4. Figma Dev Mode (Inspect)
• Copy exact CSS values
• Most reliable for precision
What’s the difference between Builder.io and Locofy.ai?
Locofy → better for generating ready-to-use React code with variants.
Builder.io → better if you need a visual editor / CMS.

Both generate code that isn’t ideal for structured systems (no tokens, no reusable components).
If I give you Builder.io code, can you turn it into a proper component system — with reusable components, variants, and the ability to update changes globally?
Yes — but Builder.io code needs transformation.

It uses inline styles, separate components, and no real variant system.

I extract:
• Colors → design tokens
• Spacing → Tailwind tokens
• Components → structured system
• Variants → unified props

Then rebuild everything as reusable components.
Result:

One clean system where you can say:
“Change Button → secondary → gap 12px”

→ updates everywhere.

My follow-up question wasn’t clear enough and shifted the focus toward speed, and that’s where things started to break.

Suddenly, the conversation shifted away from pixel-perfect results toward “fast” solutions. The AI suggested it could reconstruct a full design system from screenshots alone — something it previously required explicit values for. At this point, promise and reality started to diverge.

Learning 07

👉 Build systems step by step — and provide the token values in advance

  • AI works better when systems are built step by step, not all at once
  • Define and provide design tokens upfront (colors, typography, spacing, radius)
Learning 08

👉 AI loses context quickly — clarity requires repetition

  • It reacts to the latest input, not your overall goal
  • Repeat constraints and system rules
  • Treat each prompt as standalone
Learning 09

👉 AI answers are only as precise as the question behind them

  • What feels like “wrong” output is often a misalignment in communication
  • The goal can quickly shift — if you ask for speed, it will optimize for speed and forget accuracy.
  • It generates what is most likely, not what is correct
  • It can sound confident even when wrong
  • If you need factual accuracy, you have to explicitly demand it

So I went back to Figma and designed the app with implementation in mind:

  • Clearly defined design tokens (colors & typography only — scoped for speed)
  • Structured, reusable components (variants included)
  • Screens built with Auto Layout — responsive by default
  • Mobile-first approach with explicit breakpoints
  • Precise layout behavior — no room for interpretation

Then I used the builder.io output as a blueprint — just as recommended — to test what actually holds up in practice 👇

1. Structured component library: All components are clearly grouped and consistently organized

2. Consistent naming & variant logic: Components follow a clear naming system and predictable variant structure

3. Token-based design system: All styles are based on reusable design tokens (colors, spacing)

4. Auto Layout for real responsiveness: Every component is built with Auto Layout and adapts across sizes

5. Mobile-first & responsive Screen-Design: with clearly defined breakpoints and behavior

My goal: 🎯 I was still looking for the fastest possible way to hand over my designs. 🚀 Instead of explaining everything in detail,
I wanted to see what could be automatically extracted from the Builder.io code.

I gave him:

  • 1 Builder.io link per breakpoint and state
  • Visual references of different breakpoints and states
  • Avatar-images as 2xPNG
  • Precise instructions: A: to create a component and token system exactly like mine and B: to use Figma as a single source of truth
  • Additional logic information for each screen

Lets see if my first structured, professional prompt for Screen 1 works good enough. 👇

Refactor Approach
Let us refactor the app screen by screen and use these instructions as the foundation to build a proper component system.

We start with Screen 01: the first player opens the app and starts a new game.

–––––––––––––––––––––––

Responsive Context
The app must be built mobile-first and work especially well on mobile devices and tablets. We use the following breakpoints across the entire app:.

• S: max 479px (small phones)
• M: 480px – 767px (large phones / small tablets)
• L: 768px+ (tablets and above)

–––––––––––––––––––––––

Acceptance Criteria
• Avoid horizontal scrolling on mobile
• When the keyboard opens, the input must stay visible and move up

–––––––––––––––––––––––

Approach
Introduce strict layout and component rules based on the provided Builder.io designs and code.

These should be used as the source of truth for:
• Layout behavior
• Spacing
• Component structure
• Responsive behavior

–––––––––––––––––––––––

Important
• Do NOT rebuild the whole app
• Refactor the existing screen
• Replace current elements with reusable components

–––––––––––––––––––––––

Goal
Build a system where:
• Components are clearly named
• Variants exist (default, active, filled, etc.)
• Components can be reused and modified later

Example:
“Change component X” → should work globally

–––––––––––––––––––––––

Component Validation (Critical)
The design was fully built in Figma with structured components and variants. The Builder.io export should reflect this structure.

Your task is to verify:
• Can you detect component names?
• Can you detect variants (state, size, etc.)?
• Can you detect nested components?
• Can you detect design tokens?

If NOT:
• explicitly tell me what is missing
• tell me what you cannot read from the code
• tell me what additional input you need

EXAMPLE (IMPORTANT):
We have a component called: Name_input
It includes:
• multiple states (default, active, filled)
• multiple sizes (L, S&M)

This component is used multiple times across this screen.
Your task:
• confirm whether you can detect this component
• confirm whether you understand its variants
• confirm whether you can map it correctly into a reusable component

If something is unclear → DO NOT GUESS → ask..


–––––––––––––––––––––––

Input
Use the following Builder.io exports as the source of truth. Each screen includes layout, structure, and component information.

L Breakpoint
• 01_home_default/L
https://api.builder.io/api/v1/file/assets/TEMP/r9fhin9xivdmmw4ssc2

• 01_L_active input
https://api.builder.io/api/v1/file/assets/TEMP/7i8kw1284jimmw4wqd4

• 01_L_enabled primary, active male, filled name
https://api.builder.io/api/v1/file/assets/TEMP/61psulvtwolmmw5ocpr

M Breakpoint
• 01_home_default/M
https://api.builder.io/api/v1/file/assets/TEMP/i9g3t3prnxkmmw4t9g0

• 01_M_active input
https://api.builder.io/api/v1/file/assets/TEMP/1dmzfy0w76wmmw4xn5o

• 01_M_enabled primary, active male, filled name
https://api.builder.io/api/v1/file/assets/TEMP/zhe3ylqfgv8mmw4ykuy

S Breakpoint
• 01_S_active input
https://api.builder.io/api/v1/file/assets/TEMP/jpelhvr9m8jmmw4z8oj

• 01_S_enabled primary, active male, filled name
https://api.builder.io/api/v1/file/assets/TEMP/20cy9rp6ufzmmw4zmle

–––––––––––––––––––––––

Component Extraction
• Use the provided code as the source of truth
• Extract components based on structure in the code
• Keep naming consistent with what you find in the code

IMPORTANT:
• If components are nested (component inside component), reflect that
• Do NOT flatten the structure
• Reuse components where possible


–––––––––––––––––––––––

Variants
• Use the different states (default, active, filled, enabled, etc.) to build component variants
• Do NOT create separate components for each state

–––––––––––––––––––––––

Keyboard & Device UI
• Ignore device UI (keyboard, status bar, frames)and do NOT implement them
• The keyboard is always device-native

Instead:
• Ensure inputs scroll into view when focused
• Prevent content from being hidden behind the keyboard

–––––––––––––––––––––––

Responsive Behavior
• Derive layout behavior from the provided code and designs
• Do NOT guess
• Ensure no horizontal scrolling

–––––––––––––––––––––––

IMPORTANT:
If something is unclear or cannot be derived from the code:
• explicitly tell me what is missing
• or what you cannot confidently determine

–––––––––––––––––––––––

Goal of this Step
• Build component structure
• Validate that components and variants are correctly understood
• Make it reusable and extendable
• Reflect the structure from the code as accurately as possible

Additional to the prompt: Avatars and screenshots: One shows Screen 1 at all breakpoints, and the other shows an example of the structure of the components with variants based on the InputFieldComponent.

🧾 Results

✍️ What I intended to achieve

  • Extract tokens, components, and layout 1:1 from Figma / Builder.io
  • Build a clean, reusable component system
  • Ensure pixel-perfect behavior across MY breakpoints
    S: max 479px (small phones);
    M: 480px – 767px (large phones / small tablets);
    L: 768px+ (tablets and above)

With everything clearly defined — tokens, components, layout — this was the moment of truth. How much of the design would actually translate 1:1 into code? To break this down, I inspected the generated code and compared it directly against the design👇

A lot worked very well 🥳

  • ✅ Component structure was correctly identified 1:1
  • ✅ Components and variants were recognized 1:1
  • ✅ Reusability was considered
  • ✅ Auto layout mostly worked 1:1
  • ✅ Layout behaved generally stable
  • ✅ Responsive structure was conceptually correct
  • ✅ Design values were detected
  • ✅ Colors were correctly extracted (HEX/HSL)

What didn’t work —
and why

1. Breakpoints were ignored —
until explicitly enforced

“Use the following breakpoints across the entire app:
S: max 479px (small phones);
M: 480px – 767px (large phones / small tablets);
L: 768px+ (tablets and above)”

👉 This was not defined as a strict system — so it was treated as flexible
→ so my custom breakpoints (S / M / L) were NOT implemented
→ instead, default Tailwind breakpoints were used (sm: 640px, md: 768px)

 

🚧 I had to change the Prompt to:

❗BREAKPOINT SYSTEM MANDATORY
❗ Use exactly these breakpoints: …

❗ You MUST refer to them as: S, M, L

👉 This finally overrode Tailwind defaults and enforced my custom breakpoint system

2. Figma Line-height “auto”
was replaced by a default Tailwind value

👉 Figma value “auto” → mapped to a default Tailwind value (1.5) instead of the actual computed line-height (~1.22)

🚧 I had to replace all “auto” line-heights in Figma with explicit values
👉 This overrode Tailwind defaults and preserved the intended typography

3. Figma Max-width
broke centering

👉 In Figma, you can apply max-width to a centered & filled element without breaking alignment. 👉 In CSS, applying max-width to the flex container breaks centering.

🚧 I had to add a wrapper in Figma to match real CSS

  • wrapper → full width + centered
  • subline → max-width

👉 This aligns with how layout actually works in code

❗️ This works for text — not for full components

  • A text element can handle both fill and max-width.
  • A component cannot. It defines its own layout

👉 Combining fill (stretch) + max-width on a component breaks alignment
👉 A wrapper alone does NOT fix it

I had to advice Lovable afterwards 👉 Replacing   align-self:stretch  with   width:100%   was not enough → The system still enforced full-width behavior (w-full).  👉 Only removing the stretch behavior entirely fixed centering + max-width

A few other issues with Figma
vs Reality came up: 👀

4. Figma layering
is not transferred to CSS z-index

👉 Figma uses visual stacking (layer order)
👉 CSS uses explicit stacking (z-index + positioning)

🚧 I then had to manually set the z-index in Lovable.

5. Figma-gradient-strokes
don’t translate directly to CSS

👉 In Figma, strokes can use gradients
👉 In CSS, borders are typically solid — gradient borders are not native

👉 The gradient stroke was not reproduced as a real border
→ because CSS has no simple equivalent

 

🚧 I had to explicitly instruct Lovable to simulate the gradient stroke using layered backgrounds

background-clip was required to keep the center solid — so only the outer edge appears as a gradient border

Learning 10

👉 Figma ≠ Real CSS Constraints

  • Figma values like “auto” (e.g. line-height) do not translate reliably and often get mapped to incorrect defaults in code.
  • What visually works in Figma can break in real CSS layouts.
  • CSS requires structural separation, while Figma allows simplified setups that don’t exist in implementation.
  • Generated code must be actively corrected.
  • Figma uses visual rendering, while CSS relies on structural rules — complex effects like layering and gradients often require manual correction.

6. Visual styling was added
(blur / transparency)

I prompted: “If something is unclear → DO NOT GUESS → ask… ” & “…use the following Builder.io exports as the source of truth” 👉 Even with these instructions, the AI still interpreted the design

👉 I wasn’t strict enough in defining its role and behavior 👉 That implies design improvement freedom. So Lovable added opacity, even though it wasn’t present in the Figma design.

 

🚧 I had to change the prompt to

“CRITICAL WORKING MODE:”
❗“You are an expert Frontend Developer”
❗“You are NOT designing”
❗“You are NOT interpreting.”
❗“You are EXTRACTING a system from the provided Builder.io code.”
❗“Every decision must come from the builder.io-code.”
❗“Do NOT recreate or reinterpret.”

 

👉 This shuts down creative behavior.
Auto message from Lovable:
❌ UserBadge opacity-70 / scale →
✅ Removed (not part of the design)

Learning 11

👉 AI Does Not Follow Intent — Only Instructions

  • AI executes exactly what is specified — and needs clear boundaries.
  • Explicit prohibitions are required to prevent drift from the intended logic.
  • Precision in instructions turns unpredictable output into controlled, reliable behavior.

7. DOM didn’t show
my Figma components

After Prompt 1 and 2, I initially thought no components were created – even though Lovable said he had done so 👉 Because I couldn´t see them in DOM. But the issue wasn’t the implementation — it was visibility.

Lovable builds React Components. React “breaks down” your components into standard HTML during rendering. This makes it impossible to inspect a component using the inspector tool.

 

🚧 I had to change the Prompt to:

❗Each component MUST include a visible identifier in the DOM:
→ data-component=”ComponentName”

👉 Now my components are visible in DOM, too.

Learning 12

👉 React Components Are Invisible in the DOM by Default

  • Lovable builds React components, but they do not appear in the DOM as component names. They exist in the JavaScript code and render as regular HTML elements such as divs.
  • Only after explicitly adding data-component in Prompt 3 did the component structure become visible, making the architecture inspectable and verifiable.

8. Color tokens:
from missing → to wrong → to correct

⚠️ In Prompt 1 I forgot writing anything about Tokens:
No token instructions.
👉 Result: The model created its own token system (cave-*) based on HEX values from the builder.io-Code.

 

⚠️ In Prompt 2 I wrote:
“Use ONLY existing color and typography tokens from Figma”
👉 The model reused its previously created tokens, because Builder.io was defined as the single source of truth, while Figma was not accessible.

 

🚧 I had to change the Prompt to:

✅ Prompt 3:

1. Source of truth was consistent and unambiguous
❗️Builder.io exports are the single source of truth for:

  • …
  • color token
  • typography token

👉 No conflicting reference to Figma anymore

2. Strict execution mode

❗️You are NOT designing.
❗️You are NOT interpreting.
❗️You are BUILDING.

 

3. Strict token usage rules

  • You MUST always use color tokens in components
  • Never use hex values directly in components
  • Use EXACT token names from Builder.io code (no renaming)
  • If the token EXISTS → use it exactly as defined
  • If the token DOES NOT EXIST → add it to the token system
  • Do NOT replace missing tokens with similar ones

 

3. Tokens were fully specified via list
❗️COLORS: gelb: #F98D09; rot: #FF4E59 …

👉 The model kept its old tokens as aliases to avoid breaking existing code — but the active system now uses the correct Figma token names.

Learning 13

👉 Builder.io Code

  • I validated this in a fresh Lovable project: even without defining tokens manually, the model correctly extracted all color tokens from the Builder.io code — as long as the prompt explicitly required token-based styling and a token list.

Here is my nearly perfect final prompt 👇

14:32
Refactor this existing app into a strict, reusable design system.

We work screen by screen.

Builder.io exports are the single source of truth for:

• layout
• structure
• hierarchy
• color token
• typography token

You are NOT designing.
You are NOT interpreting.
You are BUILDING.


–––––––––––––––––––––––

STEP 1 — TOKENS (MANDATORY FIRST)

You MUST define ALL tokens BEFORE building components.

COLORS:

• braun_bg_2: #522C18
• rot: #FF4E59
• braun_logo_bg: #77462B
• braun_bg_1: #402212
• white: #EEDFD7
• gelb: #F98D09
• beige: #B1826A
• schwarz: #000000
• braun_wait: rgba(64,34,18,0.8)
• lila: #8A38F5
• beige_transparent: rgba(173,163,158,0.1)
• beige_copytext: #CFB9AE
• beige_placeholder_text: #8F7263
• grün: #34C759
• gelb_star: #DEB236
• lila_hover: #6A2ABD
• grün_hover: #20AC43
• lila_transparent: rgba(106,42,189,0.2)
• lila_transparent_hover: rgba(106,42,189,0.4)

TYPOGRAPHY:

Display:
• XXL: 48px
• XL: 40px
• L: 32px / 34px
• M: 24px
• S: 20px
• XS: 17px
• XXS: 14px

Text:
• Body: 16px / 150%
• L: 24px / 150%
• M: 20px / 150%
• S: 14px / 150%

Bold:
• L: 20px / 150%
• M: 16px / 150%
• S: 14px / 150%

RULES FOR TOKENS:

• Create tokens in:
→ index.css
→ tailwind.config.ts

• NEVER use raw values in components
• ONLY use tokens


–––––––––––––––––––––––

GOAL:

• Pixel-perfect implementation
• EXACT component structure from design
• ALL components must be real React components

Detection is NOT enough:
→ every detected component MUST be implemented


–––––––––––––––––––––––

COMPONENT RULES:

• Use EXACT names from code
• DO NOT rename
• Reuse components
• Variants via props

Example:

Button variant="primary" state="active" size="L"

• Nested components MUST be extracted
• NO duplicate components

Each component MUST include:
• data-component="ComponentName"


–––––––––––––––––––––––

BREAKPOINTS:

• S: max 479px
• M: 480–767px
• L: 768px+

• Use S / M / L naming in code

• NO guessing


–––––––––––––––––––––––

LAYOUT RULES:

• EXACT alignment from design
• NO default centering
• Respect horizontal AND vertical alignment


–––––––––––––––––––––––

RESPONSIVE RULES:

• NO horizontal scrolling on mobile
• Input must stay visible when keyboard opens


–––––––––––––––––––––––

VALIDATION STEP (MANDATORY):

Before building, answer:

• Detected components
• Detected variants
• Used tokens
• Missing / unclear parts

If something is unclear:
→ STOP and ask


–––––––––––––––––––––––

OUTPUT:

• index.css (tokens)
• tailwind.config.ts
• components/ui/*
• screen implementation

Also provide:

• component list
• variants per component
• used tokens


–––––––––––––––––––––––

INPUT:

L BREAKPOINT:

• 01_L_home default
https://api.builder.io/api/v1/file/assets/TEMP/jk7s3zvyn2imndpssmy

• 01_L_active input
https://api.builder.io/api/v1/file/assets/TEMP/n533cdy5qlmndpuf6j

• 01_L_enabled primary, active male, filled name
https://api.builder.io/api/v1/file/assets/TEMP/gcobr6j5wkimndpuuwj

M BREAKPOINT:

• 01_M_home default
https://api.builder.io/api/v1/file/assets/TEMP/6xkqy6kusnjmndpvsy3

• 01_M_active input
https://api.builder.io/api/v1/file/assets/TEMP/ii2w0btp2gsmndpwbyx

• 01_M_enabled primary, active male, filled name
https://api.builder.io/api/v1/file/assets/TEMP/5b7vdr2g21xmndpwqmn

S BREAKPOINT:

• 01_S_home default
https://api.builder.io/api/v1/file/assets/TEMP/ezs1ezjnruamndpx55u

• 01_S_active input
https://api.builder.io/api/v1/file/assets/TEMP/q5ngaa7xlnlmndpxmmu

• 01_S_enabled primary, active male, filled name
https://api.builder.io/api/v1/file/assets/TEMP/z8nnu1yu90imndpy61e

How to ask for small changes?

I wanted him to change some max-width values in one component and wrote:

“You are an expert front-end developer. I want to change the max width of the headline in “WhatsUp-Component”

1. Look at the ‘WhatsUp’ component in our project.
2. Change max width ofHeadline in “WhatsUp”-component-L to 450px.
3. Change max width of Headline in “WhatsUp”-component-M to 400px.
4. Change max width of Headline in “WhatsUp”-component-S to 300px.”

Planning: 👉 Before you start: if something is unclear: ➡️ STOP and ask.
Validation: 👉 Let me know afterward exactly what you did

👉 this worked perfectly!

How do I make the system stick — without repeating everything?

After finally getting a clean design system (tokens, components, structure), the next challenge was obvious 👉 How can I lock these rules in, so I don’t have to repeat them in every prompt? — similar to Cursor Rules? The solution was to externalize the system.

I introduce three core files:

  • instructions.md→ global rules and behavior
  • component_system.md → components, variants, updates
  • game_rules.md → screen-specific logic

💡 The idea is to shift from prompt-heavy instructions to a system-driven workflow. 👇

You must set up a structured rule system AND immediately apply it to the entire app.

This is NOT only documentation. This is ALSO implementation.


–––––––––––––––––––––––

CORE TASK

• Create these 3 files:

• instructions.md
• component_system.md
• game_rules.md

• Apply ALL rules immediately to the current app

• Refactor the app to match:

• tokens
• layout rules
• responsive rules
• component logic


–––––––––––––––––––––––

FILE 1: instructions.md

Global Instructions

• Apply to ALL screens
• Must ALWAYS be followed

General Behavior

• ❗️Builder.io exports are the single source of truth for:

• layout
• structure
• hierarchy
• color tokens
• typography tokens

• ❗️You are NOT designing

• ❗️You are NOT interpreting

• ❗️You are BUILDING

• Do NOT guess

• If unclear → ask

• If not derivable from builder.io code → say it clearly


–––––––––––––––––––––––

Component System (CRITICAL)

General Rules

• Always build reusable components
• Never create duplicates
• Always reuse existing components
• Decisions based on names, not visuals
• Use EXACT naming from builder.io code

Component Detection (STRICT)

• Extract component names from builder.io code
• Compare with existing components

Rules:

• Name matches → SAME component
• Name does not exist → NEW component
• No guessing based on visuals
• Only use explicit naming

Variants vs Updates

• Existing component + new variant → ADD
• New component → CREATE

Variant Detection

• Derived from:

• state
• size
• naming in builder.io code

Rules:

• Existing → UPDATE
• New → ADD
• Never invent

Global Updates (STRICT)

• Always global
• Never local overrides
• Never duplicate instead of updating

Reporting (MANDATORY)

• Updated components
• Added variants
• New components

Component Structure

• Extract from builder.io code
• Respect nesting
• Do NOT flatten
• Match EXACT structure


–––––––––––––––––––––––

TOKENS (MANDATORY — FIRST STEP)

❗️STEP 1 — TOKENS (MANDATORY FIRST)

• You MUST define ALL tokens BEFORE building components
• Tokens must be extracted from builder.io code
• Tokens are NOT optional

Token Rules

• ❗️NEVER use raw values in components

• ❗️ONLY use tokens

• No hex values
• No px values
• No raw font sizes
• No raw spacing

• Use EXACT token naming from builder.io code
• Do NOT rename tokens

Implementation

• index.css → token definitions (source of truth)
• tailwind.config.ts → token usage mapping

Color Tokens

• braun_bg_1 → #402212
• braun_bg_2 → #522C18
• braun_logo_bg → #77462B
• white → #EEDFD7
• schwarz → #000000
• gelb → #F98D09
• gelb_star → #DEB236
• lila → #8A38F5
• lila_hover → #6A2ABD
• grün → #34C759
• grün_hover → #20AC43
• beige → #B1826A
• beige_copytext → #CFB9AE
• beige_placeholder_text → #8F7263
• beige_transparent → rgba(173,163,158,0.1)
• lila_transparent → rgba(106,42,189,0.2)
• lila_transparent_hover → rgba(106,42,189,0.4)
• braun_wait → rgba(64,34,18,0.8)

Gradient Tokens

• --gelb_lila: linear-gradient(180deg, #F98D09 0%, #8A38F5 100%)
• --gradient_einsilbi: linear-gradient(180deg, #C1637F 11.06%, #8A38F5 100%)
• --gradient_button: linear-gradient(90deg, var(--lila) 0%, #9646FF 100%)
• --gradient_button_hover: linear-gradient(90deg, var(--lila_hover) 0%, #7333C8 100%)
• --gradient_button_gruen_hover: linear-gradient(91deg, var(--grün_hover) 0.86%, #3DB75C 98.97%)
• --gradient_button_gruen: linear-gradient(91deg, var(--grün) -3.81%, #63D37F 110.31%)

Typo Tokens

Display:
• XXL → 48/56
• XL → 40/42
• L → 32/34
• M → 24/27
• S → 20/25
• XS → 17/21
• XXS → 14/17

Text:
• Body → 16/150
• L → 24/150
• M → 20/150
• S → 14/150

Text Bold:
• L → 20/150
• M → 16/150
• S → 14/150


–––––––––––––––––––––––

Responsive & Layout

Breakpoints

• S: max 479px
• M: 480–767px
• L: 768px+

Rules

• No horizontal scroll on mobile
• Layout adapts to viewport
• No height break

Global Behavior (CRITICAL)

• Portrait only (no landscape)
• No horizontal scroll
• Keyboard:

• visual only
• layout shifts
• input visible

• Background:

• braun_bg_1
• applied globally
• no white gaps


–––––––––––––––––––––––

File Management

game_rules.md

• Add / update
• No duplicates
• Structured

component_system.md

• Track:

• components
• variants
• updates


–––––––––––––––––––––––

Working Process

For every screen:

1. Analyze builder.io code
2. Extract tokens
3. Define tokens (index.css + tailwind.config.ts)
4. Extract components
5. Implement components
6. Apply:

• update / variant / new

7. Validate:

• naming
• variants
• structure

8. Apply responsive behavior
9. No raw values


–––––––––––––––––––––––

Implementation Rules

Components

• Exact naming
• Reuse always
• Variants via props
• No duplicates
• Extract nested
• Extend, never recreate
• Add:

• data-component="ComponentName"

Tokens

• Only tokens
• No raw values
• No inline raw styles

Breakpoints

• S / M / L exact
• Must match builder.io code

Layout

• No assumptions
• Match design exactly


–––––––––––––––––––––––

Validation (MANDATORY)

• Components correct
• Variants correct
• Structure correct

If not:

• state missing
• state unclear


–––––––––––––––––––––––

FILE 2: component_system.md

• Component: [Name]
• Variants:

• size
• state

• Notes
• Updates:

• UPDATE: description


–––––––––––––––––––––––

FILE 3: game_rules.md

• SCREEN [NUMBER] — [NAME]
• Rule:

• Logic
• UI Behavior


–––––––––––––––––––––––

IMMEDIATE REFACTOR TASK

• Replace ALL colors with tokens
• Replace ALL typography with tokens
• Remove ALL raw values
• Fix layout (scroll, keyboard, portrait)
• Apply global background
• Update components (naming, variants, reuse)


–––––––––––––––––––––––

FINAL RULE

• Always use these files
• Always update them
• Always enforce them


–––––––––––––––––––––––

bitte füge das hier noch sinnvoll ein.. keine dopplungen ✌️

bitte plane vorher wie es schaffst, keine einzige anweisung zu vergessen!. alle meine anweisungen sollen zu 100% im text vorkommen. ich brauche einen einzigen copierbaren text für Lovable AI.


–––––––––––––––––––––––

Typography Token Visibility (MANDATORY)

• Ensure all components reflect the typography tokens defined in builder.io code
• Do NOT modify unrelated styles while doing this

DOM Visibility

For EVERY component using typography:

• Add:
• data-typo-token="[type]-[size]"

Examples:

• display-xl
• text-m
• text-bold-s

Rules

• The attribute must match the token used in the component
• This is for visibility only (no style changes)
• Do NOT replace or modify color classes
• Do NOT modify existing styling logic

Validation

• Typography tokens match builder.io code
• No outdated values remain
• DOM attributes are correctly applied
• No color styles are affected

Report

• Components updated with data-typo-token
• Any mismatches found

The following files 👇 are now stored in lovable, which I can reference in any future prompt.

🎯 From here on, each new prompt simply references these files and tells the AI to:

→ read them again
→ follow them strictly
→ update them if needed

Now the question is:
👉 Is this enough to make the system stable over time?

• You are implementing a new screen based on Builder.io code.
• (single source of truth)

• You MUST strictly follow:
  • instructions.md (read it again before implementing)!
  • Read instructions.md carefully
  • Follow ALL rules from instructions.md
  • Apply all rules to this screen

Validation:

• Update component_system.md and game_rules.md
• Tell me what you did.


–––––––––––––––––––––––

SCREEN 02 — Player 1 invite a friend


–––––––––––––––––––––––

CONTEXT

• Who is the user: Player 1 (already entered name + selected sex in Screen 1)
• What is happening: Player 1 wants to invite Player 2 via link
• Goal of this screen: Share invite link and wait for Player 2 to join


–––––––––––––––––––––––

GAME RULES

• Player 1 comes from Screen 1 via "Spiel Neu Los"
• Hero Header uses state: "Wait"
• the right UserBadge MUST show opposite sex-variant of Player 1
• the right UserBadge rotates continuously (360° loop) until Player 2 joins

Link kopieren

• Copies invite link
• Shows success message (top-left)
• Message disappears after 2 seconds

Freund einladen

• Opens native share dialog (iOS + Android)
• Shares invite link

Navigation

• Invite link leads Player 2 to SCREEN 03


–––––––––––––––––––––––

BUTTON STATES (HOVER)

• Primary + Secondary buttons must have hover states (all breakpoints)

M&L Secondary
{"absoluteHtml":[{"id":"e4bvilcw4awmnnaw2ns","url":"/api/v1/file/assets/TEMP/e4bvilcw4awmnnaw2ns","fileName":".figma-design-Buttons.figma.html"}]}

S Secondary
{"absoluteHtml":[{"id":"crikxqcc5momnnb2rhl","url":"/api/v1/file/assets/TEMP/crikxqcc5momnnb2rhl","fileName":".figma-design-Buttons.figma.html"}]}

M&L Primary
{"absoluteHtml":[{"id":"dsftzqnpsunmnnaxkls","url":"/api/v1/file/assets/TEMP/dsftzqnpsunmnnaxkls","fileName":".figma-design-Buttons.figma.html"}]}

S Primary
{"absoluteHtml":[{"id":"ppazlmwr61fmnnb1pz1","url":"/api/v1/file/assets/TEMP/ppazlmwr61fmnnb1pz1","fileName":".figma-design-Buttons.figma.html"}]}


–––––––––––––––––––––––

BUILDER.IO CODE

Breakpoint S

• 02_freund_einladen_S
{"absoluteHtml":[{"id":"8s4ee9ck01gmnncmo5w","url":"/api/v1/file/assets/TEMP/8s4ee9ck01gmnncmo5w","fileName":".figma-design-02_freund_einladen_S.figma.html"}]}

• 02_S_player clicked "link kopieren"
{"absoluteHtml":[{"id":"h42gtcwgl6mnncn5eq","url":"/api/v1/file/assets/TEMP/h42gtcwgl6mnncn5eq","fileName":".figma-design-02_S_player clicked \"link kopieren\".figma.html"}]}


Breakpoint M

• 02_freund_einladen_M
{"absoluteHtml":[{"id":"rr84s3vdsjhmnnclnwh","url":"/api/v1/file/assets/TEMP/rr84s3vdsjhmnnclnwh","fileName":".figma-design-02_freund_einladen_M.figma.html"}]}

• 02_M_ player clicked "link kopieren"
{"absoluteHtml":[{"id":"hsmerg8qfsumnncm4d9","url":"/api/v1/file/assets/TEMP/hsmerg8qfsumnncm4d9","fileName":".figma-design-02_M_ player clicked \"link kopieren\".figma.html"}]}


Breakpoint L

• 02_freund_einladen_L
{"absoluteHtml":[{"id":"hfri96lb7u9mnnckp6f","url":"/api/v1/file/assets/TEMP/hfri96lb7u9mnnckp6f","fileName":".figma-design-02_freund_einladen_L.figma.html"}]}

• 02_L_ player clicked "link kopieren"
{"absoluteHtml":[{"id":"diutwfumll4mnncl8af","url":"/api/v1/file/assets/TEMP/diutwfumll4mnncl8af","fileName":".figma-design-02_L_ player clicked \"link kopieren\".figma.html"}]}

How to Enforce Global Changes

I wanted him to change the UserBadge Component due the border gradient and layer issue. This was my perfectely working Prompt  👇

You are modifying the component: UserBadge

You MUST strictly follow instructions.md

• You´re a CSS pro.
• If anything is unclear or you can´t find the color token, please let me know before you start building!

GLOBAL COMPONENT CHANGE (CRITICAL)
• Update the component: UserBadge
• Apply this change to the variant:
  • state: wait
• This change MUST affect ALL usages of this component across the entire app

VISUAL STRUCTURE (MANDATORY)
• The UserBadge (state: wait) MUST be built using 2 separate layers:

• 1. OUTER LAYER (BORDER)
  • MUST use gradient token:
    • var(--gelb_lila)
  • MUST be implemented as border via background (border-box)
  • MUST remain fully visible and saturated

• 2. INNER LAYER (CONTENT)
  • Contains:
    • avatar image
    • brown overlay:
      • hsla(var(--braun-wait) / 0.8)
  • MUST be a separate inner element
  • MUST NOT affect the border

STRICT RULES
• The gradient border MUST NOT be dimmed, blended or affected by any overlay
• The overlay MUST NOT be applied on the same element as the gradient
• The gradient MUST NOT be merged with any other background layer

FORBIDDEN
• Do NOT apply overlay and gradient on the same element
• Do NOT reduce opacity of the gradient
• Do NOT simulate the border using a single background

IMPLEMENTATION REQUIREMENT
• Use layered structure:

• Outer container:
  • background: var(--gelb_lila) border-box

• Inner element:
  • avatar
  • overlay

VALIDATION
• Update component_system.md
• Ensure ALL instances of UserBadge (state: wait) use this structure
• No duplicated or overridden versions allowed
• Tell me what you changed

How to hand over complex components

While implementing the first game chat screen, it became clear that the player badge at the top—the most complex component in the entire game—was not implemented correctly.

Important structural details and variant logic were not interpreted properly via the builder.io code.

👇 See the result below.

The FIX:
Source: single Builder.io Links per variant
Variants: Other: 3 Variants: 1. Role: (guess/explain) 2. Size (M&L/S) 3. State (Default/Club_active/Club_strike) –> role:explain can use all states from State ((Default/Club_active/Club_strike); role:guess uses only the default state

👉  Here, the only additional issue that needs to be resolved is the well-known problem with the Z-index

Learning 14

👉 Builder.io Code Works Best per Component

  • Full-screen inputs are useful for speed, but complex components require isolated, detailed input to be interpreted correctly.
  • For complex components on a screen, pass Builder.io Code per component rather than per screen.

How to force him to use already implemented variants

When working with already implemented components, it’s not enough to define variants—you must explicitly enforce that the correct variant is rendered in each state.
👇 this prompt part additional to the builder.io code of the whole screen was not enough

🟡 STATE 1 — warten_auf_spieler2
PlayerBadge behavior…
state: default — “userBadge”: wait

WAIT behavior
“userBadge”: wait (Player_02) MUST:

  • rotate 360°
  • smooth animation
  • loop continuously
  • until Player_02 joins

After (Fix):
I added a strict state-to-UI binding:
“In state X, component Y MUST render variant Z. This is required and must be visible.

👇 Only now it has used the “wait” variant of the “userBadge” component, which was already known.

When you think the AI “lies” to you — and it’s actually your fault

At some point in this process, I kept feeling like the AI was straight up lying to me. It said something was fixed — and the DOM clearly showed it wasn’t.

But looking closer, there was always a reason. Every “wrong” output actually followed a rule I had defined earlier.

👉 It didn’t ignore my instructions.
👉 It followed them more strictly than I expected.

One sentence broke my system (and made the AI ignore me): It turned out, a single “MUST” in my instructions quietly overruled everything I said.

While reviewing a new component, we noticed that the typotoken did not match the figma/builder.io code. See the conversation below 👇

- look at our "bubble" component.
- Find these 2 variants: "emoji" and "emoji wort"
- tell me which color token in different sizes are currently implemented
Typograpy (all Sizes):

S (<480px): typo-bold-l 20px/150%/700

M (≥ 480px) typo-bold-xl 24px/150%/700

L (≥ 768px) typo-bold-xl 24px/150%/700
Okay, that´s absolutely right! But as you can see in the screenshot, you´re currently using

- “typo-bold-l” for sizes M&L.

That`s wrong. You need to use “typo-bold-xl” for sizes M and L. Change that for both versions (‘Emoji’ and “Emoji-Word”).
Small apps usually stay within the free tier.
Okay — let’s build a 2-player PWA version with a Lovable Cloud Backend.
Game rules: 2 players join via a link, one starts the game and invites the other. Then both are in a live chat.
One player gets a word and has to explain it using only one-syllable words.
Everything happens live in the chat, you can type or even speak, and the other person sees single words as bubbles in chat instantly.
If Player 1 uses a word with more than one syllable, the system should highlight that word. The other player can then award a penalty point by swinging the club, and Player 1 loses a point. A new word appears, and the round continues as long as the timer is still running.
If the word is guessed correctly, the guesser gets one point and the explainer gets three points. Here, too, a new word appears for the explainer as long as time hasn’t run out. The goal is to score as many points as possible over the course of four rounds. Both players take turns explaining and guessing.
For that, I´ll need your ElevenLabs API key. Do you already have one, or should I show you how to get one?
High accuracy when speaking into the mic and ensuring that the right word is actually recognized is absolutely crucial in this game. But do we really need ElevenLabs for a simple speech-to-text feature? Is it free?
Yes, for higher accuracy with ElevenLabs Scribe, you need an API key. The difference: Web Speech API (free): .. ElevenLabs Scribe (API key required): ... For a word game where every word must be recognized correctly, the higher accuracy makes sense.
OK, here´s the API key for speech-to-text and also for sound effects for later.
Got it. Building the full game now.
11:44
Game ready: Real-time, scoring, timer and word validation included.